Annotation of hatari/src/cpu/fpp.c, revision 1.1.1.2

1.1       root        1: /*
                      2: * UAE - The Un*x Amiga Emulator
                      3: *
                      4: * MC68881 emulation
                      5: *
                      6: * Copyright 1996 Herman ten Brugge
                      7: * Modified 2005 Peter Keunecke
                      8: */
                      9: 
                     10: #define __USE_ISOC9X  /* We might be able to pick up a NaN */
                     11: 
                     12: #include <math.h>
                     13: #include <float.h>
                     14: 
                     15: #include "sysconfig.h"
                     16: #include "sysdeps.h"
                     17: 
                     18: #include "options_cpu.h"
                     19: #include "memory.h"
                     20: #include "custom.h"
                     21: #include "events.h"
                     22: #include "newcpu.h"
                     23: //#include "ersatz.h"
                     24: #include "md-fpp.h"
                     25: #include "savestate.h"
                     26: #include "cpu_prefetch.h"
                     27: #include "main.h"
                     28: #include "cpummu.h"
                     29: 
                     30: #define DEBUG_FPP 0
                     31: #define write_log printf
                     32: 
                     33: STATIC_INLINE int isinrom (void)
                     34: {
                     35:        return (munge24 (m68k_getpc ()) & 0xFFF80000) == 0xF80000 && !currprefs.mmu_model;
                     36: }
                     37: 
                     38: static uae_u32 xhex_pi[]    ={0x2168c235, 0xc90fdaa2, 0x4000};
                     39: uae_u32 xhex_exp_1[] ={0xa2bb4a9a, 0xadf85458, 0x4000};
                     40: static uae_u32 xhex_l2_e[]  ={0x5c17f0bc, 0xb8aa3b29, 0x3fff};
                     41: static uae_u32 xhex_ln_2[]  ={0xd1cf79ac, 0xb17217f7, 0x3ffe};
                     42: uae_u32 xhex_ln_10[] ={0xaaa8ac17, 0x935d8ddd, 0x4000};
                     43: uae_u32 xhex_l10_2[] ={0xfbcff798, 0x9a209a84, 0x3ffd};
                     44: uae_u32 xhex_l10_e[] ={0x37287195, 0xde5bd8a9, 0x3ffd};
                     45: uae_u32 xhex_1e16[]  ={0x04000000, 0x8e1bc9bf, 0x4034};
                     46: uae_u32 xhex_1e32[]  ={0x2b70b59e, 0x9dc5ada8, 0x4069};
                     47: uae_u32 xhex_1e64[]  ={0xffcfa6d5, 0xc2781f49, 0x40d3};
                     48: uae_u32 xhex_1e128[] ={0x80e98ce0, 0x93ba47c9, 0x41a8};
                     49: uae_u32 xhex_1e256[] ={0x9df9de8e, 0xaa7eebfb, 0x4351};
                     50: uae_u32 xhex_1e512[] ={0xa60e91c7, 0xe319a0ae, 0x46a3};
                     51: uae_u32 xhex_1e1024[]={0x81750c17, 0xc9767586, 0x4d48};
                     52: uae_u32 xhex_1e2048[]={0xc53d5de5, 0x9e8b3b5d, 0x5a92};
                     53: uae_u32 xhex_1e4096[]={0x8a20979b, 0xc4605202, 0x7525};
                     54: static uae_u32 xhex_inf[]   ={0x00000000, 0x00000000, 0x7fff};
                     55: static uae_u32 xhex_nan[]   ={0xffffffff, 0xffffffff, 0x7fff};
                     56: #if USE_LONG_DOUBLE
                     57: static long double *fp_pi     = (long double *)xhex_pi;
                     58: static long double *fp_exp_1  = (long double *)xhex_exp_1;
                     59: static long double *fp_l2_e   = (long double *)xhex_l2_e;
                     60: static long double *fp_ln_2   = (long double *)xhex_ln_2;
                     61: static long double *fp_ln_10  = (long double *)xhex_ln_10;
                     62: static long double *fp_l10_2  = (long double *)xhex_l10_2;
                     63: static long double *fp_l10_e  = (long double *)xhex_l10_e;
                     64: static long double *fp_1e16   = (long double *)xhex_1e16;
                     65: static long double *fp_1e32   = (long double *)xhex_1e32;
                     66: static long double *fp_1e64   = (long double *)xhex_1e64;
                     67: static long double *fp_1e128  = (long double *)xhex_1e128;
                     68: static long double *fp_1e256  = (long double *)xhex_1e256;
                     69: static long double *fp_1e512  = (long double *)xhex_1e512;
                     70: static long double *fp_1e1024 = (long double *)xhex_1e1024;
                     71: static long double *fp_1e2048 = (long double *)xhex_1e2048;
                     72: static long double *fp_1e4096 = (long double *)xhex_1e4096;
                     73: static long double *fp_inf    = (long double *)xhex_inf;
                     74: static long double *fp_nan    = (long double *)xhex_nan;
                     75: #else
                     76: static uae_u32 dhex_pi[]    ={0x54442D18, 0x400921FB};
                     77: static uae_u32 dhex_exp_1[] ={0x8B145769, 0x4005BF0A};
                     78: static uae_u32 dhex_l2_e[]  ={0x652B82FE, 0x3FF71547};
                     79: static uae_u32 dhex_ln_2[]  ={0xFEFA39EF, 0x3FE62E42};
                     80: static uae_u32 dhex_ln_10[] ={0xBBB55516, 0x40026BB1};
                     81: static uae_u32 dhex_l10_2[] ={0x509F79FF, 0x3FD34413};
                     82: static uae_u32 dhex_l10_e[] ={0x1526E50E, 0x3FDBCB7B};
                     83: static uae_u32 dhex_1e16[]  ={0x37E08000, 0x4341C379};
                     84: static uae_u32 dhex_1e32[]  ={0xB5056E17, 0x4693B8B5};
                     85: static uae_u32 dhex_1e64[]  ={0xE93FF9F5, 0x4D384F03};
                     86: static uae_u32 dhex_1e128[] ={0xF9301D32, 0x5A827748};
                     87: static uae_u32 dhex_1e256[] ={0x7F73BF3C, 0x75154FDD};
                     88: static uae_u32 dhex_inf[]   ={0x00000000, 0x7ff00000};
                     89: static uae_u32 dhex_nan[]   ={0xffffffff, 0x7fffffff};
                     90: static double *fp_pi     = (double *)dhex_pi;
                     91: static double *fp_exp_1  = (double *)dhex_exp_1;
                     92: static double *fp_l2_e   = (double *)dhex_l2_e;
                     93: static double *fp_ln_2   = (double *)dhex_ln_2;
                     94: static double *fp_ln_10  = (double *)dhex_ln_10;
                     95: static double *fp_l10_2  = (double *)dhex_l10_2;
                     96: static double *fp_l10_e  = (double *)dhex_l10_e;
                     97: static double *fp_1e16   = (double *)dhex_1e16;
                     98: static double *fp_1e32   = (double *)dhex_1e32;
                     99: static double *fp_1e64   = (double *)dhex_1e64;
                    100: static double *fp_1e128  = (double *)dhex_1e128;
                    101: static double *fp_1e256  = (double *)dhex_1e256;
                    102: static double *fp_1e512  = (double *)dhex_inf;
                    103: static double *fp_1e1024 = (double *)dhex_inf;
                    104: static double *fp_1e2048 = (double *)dhex_inf;
                    105: static double *fp_1e4096 = (double *)dhex_inf;
                    106: static double *fp_inf    = (double *)dhex_inf;
                    107: static double *fp_nan    = (double *)dhex_nan;
                    108: #endif
                    109: double fp_1e8 = 1.0e8;
                    110: float  fp_1e0 = 1, fp_1e1 = 10, fp_1e2 = 100, fp_1e4 = 10000;
                    111: 
                    112: #define FFLAG_Z            0x4000
                    113: #define FFLAG_N            0x0100
                    114: #define FFLAG_NAN   0x0400
                    115: 
                    116: #define MAKE_FPSR(r)  (regs).fp_result=(r)
                    117: 
                    118: static uae_u16 x87_cw_tab[] = {
                    119:        0x137f, 0x1f7f, 0x177f, 0x1b7f, /* Extended */
                    120:        0x107f, 0x1c7f, 0x147f, 0x187f, /* Single */
                    121:        0x127f, 0x1e7f, 0x167f, 0x1a7f, /* Double */
                    122:        0x137f, 0x1f7f, 0x177f, 0x1b7f  /* undefined */
                    123: };
                    124: /* Nearest, toZero, Down, Up */
                    125: static __inline__ void native_set_fpucw (uae_u32 m68k_cw)
                    126: {
                    127: #if USE_X86_FPUCW
                    128:        uae_u16 x87_cw = x87_cw_tab[(m68k_cw >> 4) & 0xf];
                    129: 
                    130: #if defined(X86_MSVC_ASSEMBLY)
                    131:        __asm {
                    132:                fldcw word ptr x87_cw
                    133:        }
                    134: #elif defined(X86_ASSEMBLY)
                    135:        __asm__ ("fldcw %0" : : "m" (*&x87_cw));
                    136: #endif
                    137: #endif
                    138: }
                    139: 
                    140: #if defined(uae_s64) /* Close enough for government work? */
                    141: typedef uae_s64 tointtype;
                    142: #else
                    143: typedef uae_s32 tointtype;
                    144: #endif
                    145: 
                    146: static void fpu_op_illg (uae_u32 opcode, int pcoffset)
                    147: {
                    148:        if ((currprefs.cpu_model == 68060 && (currprefs.fpu_model == 0 || (regs.pcr & 2)))
                    149:                || (currprefs.cpu_model == 68040 && currprefs.fpu_model == 0)) {
                    150:                        /* 68040 unimplemented/68060 FPU disabled exception.
                    151:                        * Line F exception with different stack frame.. */
                    152:                        uaecptr newpc = m68k_getpc ();
                    153:                        uaecptr oldpc = newpc - pcoffset;
                    154:                        regs.t0 = regs.t1 = 0;
                    155:                        MakeSR ();
                    156:                        if (!regs.s) {
                    157:                                regs.usp = m68k_areg (regs, 7);
                    158:                                m68k_areg (regs, 7) = regs.isp;
                    159:                        }
                    160:                        regs.s = 1;
                    161:                        m68k_areg (regs, 7) -= 4;
                    162:                        x_put_long (m68k_areg (regs, 7), oldpc);
                    163:                        m68k_areg (regs, 7) -= 4;
                    164:                        x_put_long (m68k_areg (regs, 7), oldpc);
                    165:                        m68k_areg (regs, 7) -= 2;
                    166:                        x_put_word (m68k_areg (regs, 7), 0x4000 + 11 * 4);
                    167:                        m68k_areg (regs, 7) -= 4;
                    168:                        x_put_long (m68k_areg (regs, 7), newpc);
                    169:                        m68k_areg (regs, 7) -= 2;
                    170:                        x_put_word (m68k_areg (regs, 7), regs.sr);
                    171:                        write_log ("68040/060 FPU disabled exception PC=%x\n", newpc);
                    172:                        newpc = x_get_long (regs.vbr + 11 * 4);
                    173:                        m68k_setpc (newpc);
                    174: #ifdef JIT
                    175:                        set_special (SPCFLAG_END_COMPILE);
                    176: #endif
                    177:                        return;
                    178:        }
                    179:        op_illg (opcode);
                    180: }
                    181: 
                    182: STATIC_INLINE int fault_if_no_fpu (uae_u32 opcode, int pcoffset)
                    183: {
                    184:        if ((regs.pcr & 2) || currprefs.fpu_model <= 0) {
                    185:                fpu_op_illg (opcode, pcoffset);
                    186:                return 1;
                    187:        }
                    188:        return 0;
                    189: }
                    190: 
                    191: static int get_fpu_version (void)
                    192: {
                    193:        int v = 0;
                    194: 
                    195:        if (currprefs.fpu_revision >= 0)
                    196:                return currprefs.fpu_revision;
                    197:        switch (currprefs.fpu_model)
                    198:        {
                    199:        case 68881:
                    200:                v = 0x1f;
                    201:                break;
                    202:        case 68882:
                    203:                v = 0x20; /* ??? */
                    204:                break;
                    205:        case 68040:
                    206:                v = 0x41;
                    207:                break;
                    208:        }
                    209:        return v;
                    210: }
                    211: 
                    212: #define fp_round_to_minus_infinity(x) fp_floor(x)
                    213: #define fp_round_to_plus_infinity(x) fp_ceil(x)
                    214: #define fp_round_to_zero(x) ((int)(x))
                    215: #define fp_round_to_nearest(x) ((int)((x) + 0.5))
                    216: 
                    217: STATIC_INLINE tointtype toint (fptype src, fptype minval, fptype maxval)
                    218: {
                    219:        if (src < minval)
                    220:                src = minval;
                    221:        if (src > maxval)
                    222:                src = maxval;
                    223: #if defined(X86_MSVC_ASSEMBLY)
                    224:        {
                    225:                fptype tmp_fp;
                    226:                __asm {
                    227:                        fld  LDPTR src
                    228:                                frndint
                    229:                                fstp LDPTR tmp_fp
                    230:                }
                    231:                return (tointtype)tmp_fp;
                    232:        }
                    233: #else /* no X86_MSVC */
                    234:        {
                    235:                int result = src;
                    236: #if 0
                    237:        switch (get_fpcr () & 0x30) {
                    238:                case FPCR_ROUND_ZERO:
                    239:                        result = fp_round_to_zero (src);
                    240:                        break;
                    241:                case FPCR_ROUND_MINF:
                    242:                        result = fp_round_to_minus_infinity (src);
                    243:                        break;
                    244:                case FPCR_ROUND_NEAR:
                    245:                        result = fp_round_to_nearest (src);
                    246:                        break;
                    247:                case FPCR_ROUND_PINF:
                    248:                        result = fp_round_to_plus_infinity (src);
                    249:                        break;
                    250:                default:
                    251:                        result = src; /* should never be reached */
                    252:                        break;
                    253: #endif
                    254:                return result;
                    255:        }
                    256: #endif
                    257: }
                    258: 
                    259: /*extern int isinf (double x);  //Not used */
                    260: 
                    261: uae_u32 get_fpsr (void)
                    262: {
                    263:        uae_u32 answer = regs.fpsr & 0x00ffffff;
                    264: #ifdef HAVE_ISNAN
                    265:        if (isnan (regs.fp_result))
                    266:                answer |= 0x01000000;
                    267:        else
                    268: #endif
                    269:        {
                    270:                if (regs.fp_result == 0)
                    271:                        answer |= 0x04000000;
                    272:                else if (regs.fp_result < 0)
                    273:                        answer |= 0x08000000;
                    274: #ifdef HAVE_ISINF
                    275:                if (isinf (regs.fp_result))
                    276:                        answer |= 0x02000000;
                    277: #endif
                    278:        }
                    279:        return answer;
                    280: }
                    281: 
                    282: STATIC_INLINE void set_fpsr (uae_u32 x)
                    283: {
                    284:        regs.fpsr = x;
                    285: 
                    286:        if (x & 0x01000000) {
                    287:                regs.fp_result = *fp_nan;
                    288:        }
                    289:        else if (x & 0x04000000)
                    290:                regs.fp_result = 0;
                    291:        else if (x & 0x08000000)
                    292:                regs.fp_result = -1;
                    293:        else
                    294:                regs.fp_result = 1;
                    295: }
                    296: 
                    297: /* single   : S  8*E 23*F */
                    298: /* double   : S 11*E 52*F */
                    299: /* extended : S 15*E 64*F */
                    300: /* E = 0 & F = 0 -> 0 */
                    301: /* E = MAX & F = 0 -> Infin */
                    302: /* E = MAX & F # 0 -> NotANumber */
                    303: /* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */
                    304: 
                    305: STATIC_INLINE fptype to_pack (uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
                    306: {
                    307:        fptype d;
                    308:        char *cp;
                    309:        char str[100];
                    310: 
                    311:        cp = str;
                    312:        if (wrd1 & 0x80000000)
                    313:                *cp++ = '-';
                    314:        *cp++ = (wrd1 & 0xf) + '0';
                    315:        *cp++ = '.';
                    316:        *cp++ = ((wrd2 >> 28) & 0xf) + '0';
                    317:        *cp++ = ((wrd2 >> 24) & 0xf) + '0';
                    318:        *cp++ = ((wrd2 >> 20) & 0xf) + '0';
                    319:        *cp++ = ((wrd2 >> 16) & 0xf) + '0';
                    320:        *cp++ = ((wrd2 >> 12) & 0xf) + '0';
                    321:        *cp++ = ((wrd2 >> 8) & 0xf) + '0';
                    322:        *cp++ = ((wrd2 >> 4) & 0xf) + '0';
                    323:        *cp++ = ((wrd2 >> 0) & 0xf) + '0';
                    324:        *cp++ = ((wrd3 >> 28) & 0xf) + '0';
                    325:        *cp++ = ((wrd3 >> 24) & 0xf) + '0';
                    326:        *cp++ = ((wrd3 >> 20) & 0xf) + '0';
                    327:        *cp++ = ((wrd3 >> 16) & 0xf) + '0';
                    328:        *cp++ = ((wrd3 >> 12) & 0xf) + '0';
                    329:        *cp++ = ((wrd3 >> 8) & 0xf) + '0';
                    330:        *cp++ = ((wrd3 >> 4) & 0xf) + '0';
                    331:        *cp++ = ((wrd3 >> 0) & 0xf) + '0';
                    332:        *cp++ = 'E';
                    333:        if (wrd1 & 0x40000000)
                    334:                *cp++ = '-';
                    335:        *cp++ = ((wrd1 >> 24) & 0xf) + '0';
                    336:        *cp++ = ((wrd1 >> 20) & 0xf) + '0';
                    337:        *cp++ = ((wrd1 >> 16) & 0xf) + '0';
                    338:        *cp = 0;
1.1.1.2 ! root      339: #if USE_LONG_DOUBLE
        !           340:        sscanf (str, "%Le", &d);
        !           341: #else
1.1       root      342:        sscanf (str, "%le", &d);
1.1.1.2 ! root      343: #endif
1.1       root      344:        return d;
                    345: }
                    346: 
                    347: STATIC_INLINE void from_pack (fptype src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
                    348: {
                    349:        int i;
                    350:        int t;
                    351:        char *cp;
                    352:        char str[100];
                    353: 
1.1.1.2 ! root      354: #if USE_LONG_DOUBLE
        !           355:        sprintf (str, "%.16Le", src);
        !           356: #else
1.1       root      357:        sprintf (str, "%.16e", src);
1.1.1.2 ! root      358: #endif
1.1       root      359:        cp = str;
                    360:        *wrd1 = *wrd2 = *wrd3 = 0;
                    361:        if (*cp == '-') {
                    362:                cp++;
                    363:                *wrd1 = 0x80000000;
                    364:        }
                    365:        if (*cp == '+')
                    366:                cp++;
                    367:        *wrd1 |= (*cp++ - '0');
                    368:        if (*cp == '.')
                    369:                cp++;
                    370:        for (i = 0; i < 8; i++) {
                    371:                *wrd2 <<= 4;
                    372:                if (*cp >= '0' && *cp <= '9')
                    373:                        *wrd2 |= *cp++ - '0';
                    374:        }
                    375:        for (i = 0; i < 8; i++) {
                    376:                *wrd3 <<= 4;
                    377:                if (*cp >= '0' && *cp <= '9')
                    378:                        *wrd3 |= *cp++ - '0';
                    379:        }
                    380:        if (*cp == 'e' || *cp == 'E') {
                    381:                cp++;
                    382:                if (*cp == '-') {
                    383:                        cp++;
                    384:                        *wrd1 |= 0x40000000;
                    385:                }
                    386:                if (*cp == '+')
                    387:                        cp++;
                    388:                t = 0;
                    389:                for (i = 0; i < 3; i++) {
                    390:                        if (*cp >= '0' && *cp <= '9')
                    391:                                t = (t << 4) | (*cp++ - '0');
                    392:                }
                    393:                *wrd1 |= t << 16;
                    394:        }
                    395: }
                    396: 
                    397: STATIC_INLINE int get_fp_value (uae_u32 opcode, uae_u16 extra, fptype *src)
                    398: {
                    399:        uaecptr tmppc;
                    400:        uae_u16 tmp;
                    401:        int size, mode, reg;
                    402:        uae_u32 ad = 0;
                    403:        static const int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 };
                    404:        static const int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
                    405: 
                    406:        if (!(extra & 0x4000)) {
                    407:                *src = regs.fp[(extra >> 10) & 7];
                    408:                return 1;
                    409:        }
                    410:        mode = (opcode >> 3) & 7;
                    411:        reg = opcode & 7;
                    412:        size = (extra >> 10) & 7;
                    413: 
                    414:        switch (mode) {
                    415:                case 0:
                    416:                        switch (size) {
                    417:                case 6:
                    418:                        *src = (fptype) (uae_s8) m68k_dreg (regs, reg);
                    419:                        break;
                    420:                case 4:
                    421:                        *src = (fptype) (uae_s16) m68k_dreg (regs, reg);
                    422:                        break;
                    423:                case 0:
                    424:                        *src = (fptype) (uae_s32) m68k_dreg (regs, reg);
                    425:                        break;
                    426:                case 1:
                    427:                        *src = to_single (m68k_dreg (regs, reg));
                    428:                        break;
                    429:                default:
                    430:                        return 0;
                    431:                        }
                    432:                        return 1;
                    433:                case 1:
                    434:                        return 0;
                    435:                case 2:
                    436:                        ad = m68k_areg (regs, reg);
                    437:                        break;
                    438:                case 3:
                    439:                        ad = m68k_areg (regs, reg);
                    440:                        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
                    441:                        break;
                    442:                case 4:
                    443:                        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
                    444:                        ad = m68k_areg (regs, reg);
                    445:                        break;
                    446:                case 5:
                    447:                        ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_next_iword ();
                    448:                        break;
                    449:                case 6:
                    450:                        ad = x_get_disp_ea_020 (m68k_areg (regs, reg), x_next_iword ());
                    451:                        break;
                    452:                case 7:
                    453:                        switch (reg) {
                    454:                case 0:
                    455:                        ad = (uae_s32) (uae_s16) x_next_iword ();
                    456:                        break;
                    457:                case 1:
                    458:                        ad = x_next_ilong ();
                    459:                        break;
                    460:                case 2:
                    461:                        ad = m68k_getpc ();
                    462:                        ad += (uae_s32) (uae_s16) x_next_iword ();
                    463:                        break;
                    464:                case 3:
                    465:                        tmppc = m68k_getpc ();
                    466:                        tmp = x_next_iword ();
                    467:                        ad = x_get_disp_ea_020 (tmppc, tmp);
                    468:                        break;
                    469:                case 4:
                    470:                        ad = m68k_getpc ();
                    471:                        m68k_setpc (ad + sz2[size]);
                    472:                        if (size == 6)
                    473:                                ad++;
                    474:                        break;
                    475:                default:
                    476:                        return 0;
                    477:                        }
                    478:        }
                    479:        switch (size) {
                    480:                case 0:
                    481:                        *src = (fptype) (uae_s32) x_get_long (ad);
                    482:                        break;
                    483:                case 1:
                    484:                        *src = to_single (x_get_long (ad));
                    485:                        break;
                    486:                case 2:{
                    487:                        uae_u32 wrd1, wrd2, wrd3;
                    488:                        wrd1 = x_get_long (ad);
                    489:                        ad += 4;
                    490:                        wrd2 = x_get_long (ad);
                    491:                        ad += 4;
                    492:                        wrd3 = x_get_long (ad);
                    493:                        *src = to_exten (wrd1, wrd2, wrd3);
                    494:                           }
                    495:                           break;
                    496:                case 3:{
                    497:                        uae_u32 wrd1, wrd2, wrd3;
                    498:                        wrd1 = x_get_long (ad);
                    499:                        ad += 4;
                    500:                        wrd2 = x_get_long (ad);
                    501:                        ad += 4;
                    502:                        wrd3 = x_get_long (ad);
                    503:                        *src = to_pack (wrd1, wrd2, wrd3);
                    504:                           }
                    505:                           break;
                    506:                case 4:
                    507:                        *src = (fptype) (uae_s16) x_get_word (ad);
                    508:                        break;
                    509:                case 5:{
                    510:                        uae_u32 wrd1, wrd2;
                    511:                        wrd1 = x_get_long (ad);
                    512:                        ad += 4;
                    513:                        wrd2 = x_get_long (ad);
                    514:                        *src = to_double (wrd1, wrd2);
                    515:                           }
                    516:                           break;
                    517:                case 6:
                    518:                        *src = (fptype) (uae_s8) x_get_byte (ad);
                    519:                        break;
                    520:                default:
                    521:                        return 0;
                    522:        }
                    523:        return 1;
                    524: }
                    525: 
                    526: STATIC_INLINE int put_fp_value (fptype value, uae_u32 opcode, uae_u16 extra)
                    527: {
                    528:        uae_u16 tmp;
                    529:        uaecptr tmppc;
                    530:        int size, mode, reg;
                    531:        uae_u32 ad;
                    532:        static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 };
                    533:        static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
                    534: 
                    535: #if DEBUG_FPP
                    536:        if (!isinrom ())
                    537:                write_log ("PUTFP: %f %04X %04X\n", value, opcode, extra);
                    538: #endif
                    539:        if (!(extra & 0x4000)) {
                    540:                regs.fp[(extra >> 10) & 7] = value;
                    541:                return 1;
                    542:        }
                    543:        reg = opcode & 7;
                    544:        mode = (opcode >> 3) & 7;
                    545:        size = (extra >> 10) & 7;
                    546:        ad = -1;
                    547:        switch (mode) {
                    548:                case 0:
                    549:                        switch (size) {
                    550:                case 6:
                    551:                        m68k_dreg (regs, reg) = (uae_u32)(((toint (value, -128.0, 127.0) & 0xff)
                    552:                                | (m68k_dreg (regs, reg) & ~0xff)));
                    553:                        break;
                    554:                case 4:
                    555:                        m68k_dreg (regs, reg) = (uae_u32)(((toint (value, -32768.0, 32767.0) & 0xffff)
                    556:                                | (m68k_dreg (regs, reg) & ~0xffff)));
                    557:                        break;
                    558:                case 0:
                    559:                        m68k_dreg (regs, reg) = (uae_u32)toint (value, -2147483648.0, 2147483647.0);
                    560:                        break;
                    561:                case 1:
                    562:                        m68k_dreg (regs, reg) = from_single (value);
                    563:                        break;
                    564:                default:
                    565:                        return 0;
                    566:                        }
                    567:                        return 1;
                    568:                case 1:
                    569:                        return 0;
                    570:                case 2:
                    571:                        ad = m68k_areg (regs, reg);
                    572:                        break;
                    573:                case 3:
                    574:                        ad = m68k_areg (regs, reg);
                    575:                        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
                    576:                        break;
                    577:                case 4:
                    578:                        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
                    579:                        ad = m68k_areg (regs, reg);
                    580:                        break;
                    581:                case 5:
                    582:                        ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_next_iword ();
                    583:                        break;
                    584:                case 6:
                    585:                        ad = x_get_disp_ea_020 (m68k_areg (regs, reg), x_next_iword ());
                    586:                        break;
                    587:                case 7:
                    588:                        switch (reg) {
                    589:                case 0:
                    590:                        ad = (uae_s32) (uae_s16) x_next_iword ();
                    591:                        break;
                    592:                case 1:
                    593:                        ad = x_next_ilong ();
                    594:                        break;
                    595:                case 2:
                    596:                        ad = m68k_getpc ();
                    597:                        ad += (uae_s32) (uae_s16) x_next_iword ();
                    598:                        break;
                    599:                case 3:
                    600:                        tmppc = m68k_getpc ();
                    601:                        tmp = x_next_iword ();
                    602:                        ad = x_get_disp_ea_020 (tmppc, tmp);
                    603:                        break;
                    604:                case 4:
                    605:                        ad = m68k_getpc ();
                    606:                        m68k_setpc (ad + sz2[size]);
                    607:                        break;
                    608:                default:
                    609:                        return 0;
                    610:                        }
                    611:        }
                    612:        switch (size) {
                    613:                case 0:
                    614:                        x_put_long (ad, (uae_u32)toint (value, -2147483648.0, 2147483647.0));
                    615:                        break;
                    616:                case 1:
                    617:                        x_put_long (ad, from_single (value));
                    618:                        break;
                    619:                case 2:
                    620:                        {
                    621:                                uae_u32 wrd1, wrd2, wrd3;
                    622:                                from_exten (value, &wrd1, &wrd2, &wrd3);
                    623:                                x_put_long (ad, wrd1);
                    624:                                ad += 4;
                    625:                                x_put_long (ad, wrd2);
                    626:                                ad += 4;
                    627:                                x_put_long (ad, wrd3);
                    628:                        }
                    629:                        break;
                    630:                case 3:
                    631:                        {
                    632:                                uae_u32 wrd1, wrd2, wrd3;
                    633:                                from_pack (value, &wrd1, &wrd2, &wrd3);
                    634:                                x_put_long (ad, wrd1);
                    635:                                ad += 4;
                    636:                                x_put_long (ad, wrd2);
                    637:                                ad += 4;
                    638:                                x_put_long (ad, wrd3);
                    639:                        }
                    640:                        break;
                    641:                case 4:
                    642:                        x_put_word (ad, (uae_s16) toint (value, -32768.0, 32767.0));
                    643:                        break;
                    644:                case 5:{
                    645:                        uae_u32 wrd1, wrd2;
                    646:                        from_double (value, &wrd1, &wrd2);
                    647:                        x_put_long (ad, wrd1);
                    648:                        ad += 4;
                    649:                        x_put_long (ad, wrd2);
                    650:                           }
                    651:                           break;
                    652:                case 6:
                    653:                        x_put_byte (ad, (uae_s8)toint (value, -128.0, 127.0));
                    654:                        break;
                    655:                default:
                    656:                        return 0;
                    657:        }
                    658:        return 1;
                    659: }
                    660: 
                    661: STATIC_INLINE int get_fp_ad (uae_u32 opcode, uae_u32 * ad)
                    662: {
                    663:        uae_u16 tmp;
                    664:        uaecptr tmppc;
                    665:        int mode;
                    666:        int reg;
                    667: 
                    668:        mode = (opcode >> 3) & 7;
                    669:        reg = opcode & 7;
                    670:        switch (mode) {
                    671:                case 0:
                    672:                case 1:
                    673:                        return 0;
                    674:                case 2:
                    675:                        *ad = m68k_areg (regs, reg);
                    676:                        break;
                    677:                case 3:
                    678:                        *ad = m68k_areg (regs, reg);
                    679:                        break;
                    680:                case 4:
                    681:                        *ad = m68k_areg (regs, reg);
                    682:                        break;
                    683:                case 5:
                    684:                        *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_next_iword ();
                    685:                        break;
                    686:                case 6:
                    687:                        *ad = x_get_disp_ea_020 (m68k_areg (regs, reg), x_next_iword ());
                    688:                        break;
                    689:                case 7:
                    690:                        switch (reg) {
                    691:                case 0:
                    692:                        *ad = (uae_s32) (uae_s16) x_next_iword ();
                    693:                        break;
                    694:                case 1:
                    695:                        *ad = x_next_ilong ();
                    696:                        break;
                    697:                case 2:
                    698:                        *ad = m68k_getpc ();
                    699:                        *ad += (uae_s32) (uae_s16) x_next_iword ();
                    700:                        break;
                    701:                case 3:
                    702:                        tmppc = m68k_getpc ();
                    703:                        tmp = x_next_iword ();
                    704:                        *ad = x_get_disp_ea_020 (tmppc, tmp);
                    705:                        break;
                    706:                default:
                    707:                        return 0;
                    708:                        }
                    709:        }
                    710:        return 1;
                    711: }
                    712: 
                    713: STATIC_INLINE int fpp_cond (int condition)
                    714: {
                    715:        int N = (regs.fp_result < 0.0);
                    716:        int Z = (regs.fp_result == 0.0);
                    717:        int NotANumber = 0;
                    718: 
                    719: #ifdef HAVE_ISNAN
                    720:        NotANumber = isnan (regs.fp_result);
                    721: #endif
                    722: 
                    723:        if (NotANumber)
                    724:                N=Z=0;
                    725: 
                    726:        switch (condition) {
                    727:                case 0x00:
                    728:                        return 0;
                    729:                case 0x01:
                    730:                        return Z;
                    731:                case 0x02:
                    732:                        return !(NotANumber || Z || N);
                    733:                case 0x03:
                    734:                        return Z || !(NotANumber || N);
                    735:                case 0x04:
                    736:                        return N && !(NotANumber || Z);
                    737:                case 0x05:
                    738:                        return Z || (N && !NotANumber);
                    739:                case 0x06:
                    740:                        return !(NotANumber || Z);
                    741:                case 0x07:
                    742:                        return !NotANumber;
                    743:                case 0x08:
                    744:                        return NotANumber;
                    745:                case 0x09:
                    746:                        return NotANumber || Z;
                    747:                case 0x0a:
                    748:                        return NotANumber || !(N || Z);
                    749:                case 0x0b:
                    750:                        return NotANumber || Z || !N;
                    751:                case 0x0c:
                    752:                        return NotANumber || (N && !Z);
                    753:                case 0x0d:
                    754:                        return NotANumber || Z || N;
                    755:                case 0x0e:
                    756:                        return !Z;
                    757:                case 0x0f:
                    758:                        return 1;
                    759:                case 0x10:
                    760:                        return 0;
                    761:                case 0x11:
                    762:                        return Z;
                    763:                case 0x12:
                    764:                        return !(NotANumber || Z || N);
                    765:                case 0x13:
                    766:                        return Z || !(NotANumber || N);
                    767:                case 0x14:
                    768:                        return N && !(NotANumber || Z);
                    769:                case 0x15:
                    770:                        return Z || (N && !NotANumber);
                    771:                case 0x16:
                    772:                        return !(NotANumber || Z);
                    773:                case 0x17:
                    774:                        return !NotANumber;
                    775:                case 0x18:
                    776:                        return NotANumber;
                    777:                case 0x19:
                    778:                        return NotANumber || Z;
                    779:                case 0x1a:
                    780:                        return NotANumber || !(N || Z);
                    781:                case 0x1b:
                    782:                        return NotANumber || Z || !N;
                    783:                case 0x1c:
                    784:                        return NotANumber || (N && !Z);
                    785:                case 0x1d:
                    786:                        return NotANumber || Z || N;
                    787:                case 0x1e:
                    788:                        return !Z;
                    789:                case 0x1f:
                    790:                        return 1;
                    791:        }
                    792:        return -1;
                    793: }
                    794: 
                    795: void fpuop_dbcc (uae_u32 opcode, uae_u16 extra)
                    796: {
                    797:        uaecptr pc = (uae_u32) m68k_getpc ();
                    798:        uae_s32 disp;
                    799:        int cc;
                    800: 
                    801: #if DEBUG_FPP
                    802:        if (!isinrom ())
                    803:                write_log ("fdbcc_opp at %08lx\n", m68k_getpc ());
                    804: #endif
                    805:        if (fault_if_no_fpu (opcode, 4))
                    806:                return;
                    807: 
                    808:        disp = (uae_s32) (uae_s16) x_next_iword ();
                    809:        cc = fpp_cond (extra & 0x3f);
                    810:        if (cc == -1) {
                    811:                fpu_op_illg (opcode, 4);
                    812:        } else if (!cc) {
                    813:                int reg = opcode & 0x7;
                    814: 
                    815:                m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & 0xffff0000)
                    816:                        | (((m68k_dreg (regs, reg) & 0xffff) - 1) & 0xffff));
                    817:                if ((m68k_dreg (regs, reg) & 0xffff) != 0xffff)
                    818:                        m68k_setpc (pc + disp);
                    819:        }
                    820: }
                    821: 
                    822: void fpuop_scc (uae_u32 opcode, uae_u16 extra)
                    823: {
                    824:        uae_u32 ad;
                    825:        int cc;
                    826: 
                    827: #if DEBUG_FPP
                    828:        if (!isinrom ())
                    829:                write_log ("fscc_opp at %08lx\n", m68k_getpc ());
                    830: #endif
                    831:        if (fault_if_no_fpu (opcode, 4))
                    832:                return;
                    833: 
                    834:        cc = fpp_cond (extra & 0x3f);
                    835:        if (cc == -1) {
                    836:                fpu_op_illg (opcode, 4);
                    837:        } else if ((opcode & 0x38) == 0) {
                    838:                m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | (cc ? 0xff : 0x00);
                    839:        } else {
                    840:                if (get_fp_ad (opcode, &ad) == 0) {
                    841:                        m68k_setpc (m68k_getpc () - 4);
                    842:                        op_illg (opcode);
                    843:                } else
                    844:                        x_put_byte (ad, cc ? 0xff : 0x00);
                    845:        }
                    846: }
                    847: 
                    848: void fpuop_trapcc (uae_u32 opcode, uaecptr oldpc, uae_u16 extra)
                    849: {
                    850:        int cc;
                    851: 
                    852: #if DEBUG_FPP
                    853:        if (!isinrom ())
                    854:                write_log ("ftrapcc_opp at %08lx\n", m68k_getpc ());
                    855: #endif
                    856:        if (fault_if_no_fpu (opcode, m68k_getpc() - oldpc))
                    857:                return;
                    858: 
                    859:        cc = fpp_cond (extra & 0x3f);
                    860:        if (cc == -1) {
                    861:                fpu_op_illg (opcode, m68k_getpc () - oldpc);
                    862:        }
                    863:        if (cc)
                    864:                Exception (7, oldpc - 2, M68000_EXC_SRC_CPU);
                    865: }
                    866: 
                    867: void fpuop_bcc (uae_u32 opcode, uaecptr pc, uae_u32 extra)
                    868: {
                    869:        int cc;
                    870: 
                    871: #if DEBUG_FPP
                    872:        if (!isinrom ())
                    873:                write_log ("fbcc_opp at %08lx\n", m68k_getpc ());
                    874: #endif
                    875:        if (fault_if_no_fpu (opcode, m68k_getpc () - pc))
                    876:                return;
                    877: 
                    878:        cc = fpp_cond (opcode & 0x3f);
                    879:        if (cc == -1) {
                    880:                fpu_op_illg (opcode, m68k_getpc () - pc);
                    881:        } else if (cc) {
                    882:                if ((opcode & 0x40) == 0)
                    883:                        extra = (uae_s32) (uae_s16) extra;
                    884:                m68k_setpc (pc + extra);
                    885:        }
                    886: }
                    887: 
                    888: void fpuop_save (uae_u32 opcode)
                    889: {
                    890:        uae_u32 ad;
                    891:        int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
                    892:        int fpu_version = get_fpu_version();
                    893:        int i;
                    894: 
                    895: #if DEBUG_FPP
                    896:        if (!isinrom ())
                    897:                write_log ("fsave_opp at %08lx\n", m68k_getpc ());
                    898: #endif
                    899:        if (fault_if_no_fpu (opcode, 2))
                    900:                return;
                    901: 
                    902:        if (get_fp_ad (opcode, &ad) == 0) {
                    903:                fpu_op_illg (opcode, 2);
                    904:                return;
                    905:        }
                    906: 
                    907:        if (currprefs.fpu_model == 68060) {
                    908:                /* 12 byte 68060 IDLE frame.  */
                    909:                if (incr < 0) {
                    910:                        ad -= 4;
                    911:                        x_put_long (ad, 0x00000000);
                    912:                        ad -= 4;
                    913:                        x_put_long (ad, 0x00000000);
                    914:                        ad -= 4;
                    915:                        x_put_long (ad, 0x00006000);
                    916:                } else {
                    917:                        x_put_long (ad, 0x00006000);
                    918:                        ad += 4;
                    919:                        x_put_long (ad, 0x00000000);
                    920:                        ad += 4;
                    921:                        x_put_long (ad, 0x00000000);
                    922:                        ad += 4;
                    923:                }
                    924:        } else if (currprefs.fpu_model == 68040) {
                    925:                /* 4 byte 68040 IDLE frame.  */
                    926:                if (incr < 0) {
                    927:                        ad -= 4;
                    928:                        x_put_long (ad, fpu_version << 24);
                    929:                } else {
                    930:                        x_put_long (ad, fpu_version << 24);
                    931:                        ad += 4;
                    932:                }
                    933:        } else { /* 68881/68882 */
                    934:                int idle_size = currprefs.fpu_model == 68882 ? 0x38 : 0x18;
                    935:                if (incr < 0) {
                    936:                        ad -= 4;
                    937:                        x_put_long (ad, 0x70000000);
                    938:                        for (i = 0; i < (idle_size - 1) / 4; i++) {
                    939:                                ad -= 4;
                    940:                                x_put_long (ad, 0x00000000);
                    941:                        }
                    942:                        ad -= 4;
                    943:                        x_put_long (ad, (fpu_version << 24) | (idle_size << 16));
                    944:                } else {
                    945:                        x_put_long (ad, (fpu_version << 24) | (idle_size << 16));
                    946:                        ad += 4;
                    947:                        for (i = 0; i < (idle_size - 1) / 4; i++) {
                    948:                                x_put_long (ad, 0x00000000);
                    949:                                ad += 4;
                    950:                        }
                    951:                        x_put_long (ad, 0x70000000);
                    952:                        ad += 4;
                    953:                }
                    954:        }
                    955:        if ((opcode & 0x38) == 0x18)
                    956:                m68k_areg (regs, opcode & 7) = ad;
                    957:        if ((opcode & 0x38) == 0x20)
                    958:                m68k_areg (regs, opcode & 7) = ad;
                    959: }
                    960: 
                    961: void fpuop_restore (uae_u32 opcode)
                    962: {
                    963:        uae_u32 ad;
                    964:        uae_u32 d;
                    965:        int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
                    966: 
                    967: #if DEBUG_FPP
                    968:        if (!isinrom ())
                    969:                write_log ("frestore_opp at %08lx\n", m68k_getpc ());
                    970: #endif
                    971:        if (fault_if_no_fpu (opcode, 2))
                    972:                return;
                    973: 
                    974:        if (get_fp_ad (opcode, &ad) == 0) {
                    975:                fpu_op_illg (opcode, 2);
                    976:                return;
                    977:        }
                    978: 
                    979:        if (currprefs.fpu_model == 68060) {
                    980:                /* all 68060 FPU frames are 12 bytes */
                    981:                if (incr < 0) {
                    982:                        ad -= 4;
                    983:                        d = x_get_long (ad);
                    984:                        ad -= 8;
                    985:                } else {
                    986:                        d = x_get_long (ad);
                    987:                        ad += 4;
                    988:                        ad += 8;
                    989:                }
                    990: 
                    991:        } else if (currprefs.fpu_model == 68040) {
                    992:                /* 68040 */
                    993:                if (incr < 0) {
                    994:                        /* @@@ This may be wrong.  */
                    995:                        ad -= 4;
                    996:                        d = x_get_long (ad);
                    997:                        if ((d & 0xff000000) != 0) { /* Not a NULL frame? */
                    998:                                if ((d & 0x00ff0000) == 0) { /* IDLE */
                    999:                                } else if ((d & 0x00ff0000) == 0x00300000) { /* UNIMP */
                   1000:                                        ad -= 44;
                   1001:                                } else if ((d & 0x00ff0000) == 0x00600000) { /* BUSY */
                   1002:                                        ad -= 92;
                   1003:                                }
                   1004:                        }
                   1005:                } else {
                   1006:                        d = x_get_long (ad);
                   1007:                        ad += 4;
                   1008:                        if ((d & 0xff000000) != 0) { /* Not a NULL frame? */
                   1009:                                if ((d & 0x00ff0000) == 0) { /* IDLE */
                   1010:                                } else if ((d & 0x00ff0000) == 0x00300000) { /* UNIMP */
                   1011:                                        ad += 44;
                   1012:                                } else if ((d & 0x00ff0000) == 0x00600000) { /* BUSY */
                   1013:                                        ad += 92;
                   1014:                                }
                   1015:                        }
                   1016:                }
                   1017:        } else { /* 68881/68882 */
                   1018:                if (incr < 0) {
                   1019:                        ad -= 4;
                   1020:                        d = x_get_long (ad);
                   1021:                        if ((d & 0xff000000) != 0) {
                   1022:                                if ((d & 0x00ff0000) == 0x00180000)
                   1023:                                        ad -= 6 * 4;
                   1024:                                else if ((d & 0x00ff0000) == 0x00380000)
                   1025:                                        ad -= 14 * 4;
                   1026:                                else if ((d & 0x00ff0000) == 0x00b40000)
                   1027:                                        ad -= 45 * 4;
                   1028:                        }
                   1029:                } else {
                   1030:                        d = x_get_long (ad);
                   1031:                        ad += 4;
                   1032:                        if ((d & 0xff000000) != 0) {
                   1033:                                if ((d & 0x00ff0000) == 0x00180000)
                   1034:                                        ad += 6 * 4;
                   1035:                                else if ((d & 0x00ff0000) == 0x00380000)
                   1036:                                        ad += 14 * 4;
                   1037:                                else if ((d & 0x00ff0000) == 0x00b40000)
                   1038:                                        ad += 45 * 4;
                   1039:                        }
                   1040:                }
                   1041:        }
                   1042:        if ((opcode & 0x38) == 0x18)
                   1043:                m68k_areg (regs, opcode & 7) = ad;
                   1044:        if ((opcode & 0x38) == 0x20)
                   1045:                m68k_areg (regs, opcode & 7) = ad;
                   1046: }
                   1047: 
                   1048: static void fround (int reg)
                   1049: {
                   1050:        regs.fp[reg] = (float)regs.fp[reg];
                   1051: }
                   1052: 
                   1053: void fpuop_arithmetic (uae_u32 opcode, uae_u16 extra)
                   1054: {
                   1055:        int reg;
                   1056:        fptype src;
                   1057: 
                   1058: #if DEBUG_FPP
                   1059:        if (!isinrom ())
                   1060:                write_log ("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra, m68k_getpc () - 4);
                   1061: #endif
                   1062:        if (fault_if_no_fpu (opcode, 4))
                   1063:                return;
                   1064: 
                   1065:        switch ((extra >> 13) & 0x7) {
                   1066: 
                   1067:                case 3:
                   1068:                        if (put_fp_value (regs.fp[(extra >> 7) & 7], opcode, extra) == 0) {
                   1069:                                m68k_setpc (m68k_getpc () - 4);
                   1070:                                op_illg (opcode);
                   1071:                        }
                   1072:                        return;
                   1073: 
                   1074:                case 4:
                   1075:                case 5:
                   1076:                        if ((opcode & 0x38) == 0) {
                   1077:                                if (extra & 0x2000) {
                   1078:                                        if (extra & 0x1000)
                   1079:                                                m68k_dreg (regs, opcode & 7) = regs.fpcr & 0xffff;
                   1080:                                        if (extra & 0x0800)
                   1081:                                                m68k_dreg (regs, opcode & 7) = get_fpsr ();
                   1082:                                        if (extra & 0x0400)
                   1083:                                                m68k_dreg (regs, opcode & 7) = regs.fpiar;
                   1084:                                } else {
                   1085:                                        if (extra & 0x1000) {
                   1086:                                                regs.fpcr = m68k_dreg (regs, opcode & 7);
                   1087:                                                native_set_fpucw (regs.fpcr);
                   1088:                                        }
                   1089:                                        if (extra & 0x0800)
                   1090:                                                set_fpsr (m68k_dreg (regs, opcode & 7));
                   1091:                                        if (extra & 0x0400)
                   1092:                                                regs.fpiar = m68k_dreg (regs, opcode & 7);
                   1093:                                }
                   1094:                        } else if ((opcode & 0x38) == 0x08) {
                   1095:                                if (extra & 0x2000) {
                   1096:                                        if (extra & 0x1000)
                   1097:                                                m68k_areg (regs, opcode & 7) = regs.fpcr & 0xffff;
                   1098:                                        if (extra & 0x0800)
                   1099:                                                m68k_areg (regs, opcode & 7) = get_fpsr ();
                   1100:                                        if (extra & 0x0400)
                   1101:                                                m68k_areg (regs, opcode & 7) = regs.fpiar;
                   1102:                                } else {
                   1103:                                        if (extra & 0x1000) {
                   1104:                                                regs.fpcr = m68k_areg (regs, opcode & 7);
                   1105:                                                native_set_fpucw (regs.fpcr);
                   1106:                                        }
                   1107:                                        if (extra & 0x0800)
                   1108:                                                set_fpsr (m68k_areg (regs, opcode & 7));
                   1109:                                        if (extra & 0x0400)
                   1110:                                                regs.fpiar = m68k_areg (regs, opcode & 7);
                   1111:                                }
                   1112:                        } else if ((opcode & 0x3f) == 0x3c) {
                   1113:                                if ((extra & 0x2000) == 0) {
                   1114:                                        if (extra & 0x1000) {
                   1115:                                                regs.fpcr = x_next_ilong ();
                   1116:                                                native_set_fpucw (regs.fpcr);
                   1117:                                        }
                   1118:                                        if (extra & 0x0800)
                   1119:                                                set_fpsr (x_next_ilong ());
                   1120:                                        if (extra & 0x0400)
                   1121:                                                regs.fpiar = x_next_ilong ();
                   1122:                                }
                   1123:                        } else if (extra & 0x2000) {
                   1124:                                /* FMOVEM FPP->memory */
                   1125:                                uae_u32 ad;
                   1126:                                int incr = 0;
                   1127: 
                   1128:                                if (get_fp_ad (opcode, &ad) == 0) {
                   1129:                                        m68k_setpc (m68k_getpc () - 4);
                   1130:                                        op_illg (opcode);
                   1131:                                        return;
                   1132:                                }
                   1133:                                if ((opcode & 0x38) == 0x20) {
                   1134:                                        if (extra & 0x1000)
                   1135:                                                incr += 4;
                   1136:                                        if (extra & 0x0800)
                   1137:                                                incr += 4;
                   1138:                                        if (extra & 0x0400)
                   1139:                                                incr += 4;
                   1140:                                }
                   1141:                                ad -= incr;
                   1142:                                if (extra & 0x1000) {
                   1143:                                        x_put_long (ad, regs.fpcr & 0xffff);
                   1144:                                        ad += 4;
                   1145:                                }
                   1146:                                if (extra & 0x0800) {
                   1147:                                        x_put_long (ad, get_fpsr());
                   1148:                                        ad += 4;
                   1149:                                }
                   1150:                                if (extra & 0x0400) {
                   1151:                                        x_put_long (ad, regs.fpiar);
                   1152:                                        ad += 4;
                   1153:                                }
                   1154:                                ad -= incr;
                   1155:                                if ((opcode & 0x38) == 0x18)
                   1156:                                        m68k_areg (regs, opcode & 7) = ad;
                   1157:                                if ((opcode & 0x38) == 0x20)
                   1158:                                        m68k_areg (regs, opcode & 7) = ad;
                   1159:                        } else {
                   1160:                                /* FMOVEM memory->FPP */
                   1161:                                uae_u32 ad;
                   1162:                                int incr = 0;
                   1163: 
                   1164:                                if (get_fp_ad (opcode, &ad) == 0) {
                   1165:                                        m68k_setpc (m68k_getpc () - 4);
                   1166:                                        op_illg (opcode);
                   1167:                                        return;
                   1168:                                }
                   1169:                                if((opcode & 0x38) == 0x20) {
                   1170:                                        if (extra & 0x1000)
                   1171:                                                incr += 4;
                   1172:                                        if (extra & 0x0800)
                   1173:                                                incr += 4;
                   1174:                                        if (extra & 0x0400)
                   1175:                                                incr += 4;
                   1176:                                        ad = ad - incr;
                   1177:                                }
                   1178:                                if (extra & 0x1000) {
                   1179:                                        regs.fpcr = x_get_long (ad);
                   1180:                                        native_set_fpucw (regs.fpcr);
                   1181:                                        ad += 4;
                   1182:                                }
                   1183:                                if (extra & 0x0800) {
                   1184:                                        set_fpsr(x_get_long (ad));
                   1185:                                        ad += 4;
                   1186:                                }
                   1187:                                if (extra & 0x0400) {
                   1188:                                        regs.fpiar = x_get_long (ad);
                   1189:                                        ad += 4;
                   1190:                                }
                   1191:                                if ((opcode & 0x38) == 0x18)
                   1192:                                        m68k_areg (regs, opcode & 7) = ad;
                   1193:                                if ((opcode & 0x38) == 0x20)
                   1194:                                        m68k_areg (regs, opcode & 7) = ad - incr;
                   1195:                        }
                   1196:                        return;
                   1197: 
                   1198:                case 6:
                   1199:                case 7:
                   1200:                        {
                   1201:                                uae_u32 ad, list = 0;
                   1202:                                int incr = 0;
                   1203:                                if (extra & 0x2000) {
                   1204:                                        /* FMOVEM FPP->memory */
                   1205:                                        if (get_fp_ad (opcode, &ad) == 0) {
                   1206:                                                m68k_setpc (m68k_getpc () - 4);
                   1207:                                                op_illg (opcode);
                   1208:                                                return;
                   1209:                                        }
                   1210:                                        switch ((extra >> 11) & 3) {
                   1211:                case 0: /* static pred */
                   1212:                        list = extra & 0xff;
                   1213:                        incr = -1;
                   1214:                        break;
                   1215:                case 1: /* dynamic pred */
                   1216:                        list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
                   1217:                        incr = -1;
                   1218:                        break;
                   1219:                case 2: /* static postinc */
                   1220:                        list = extra & 0xff;
                   1221:                        incr = 1;
                   1222:                        break;
                   1223:                case 3: /* dynamic postinc */
                   1224:                        list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
                   1225:                        incr = 1;
                   1226:                        break;
                   1227:                                        }
                   1228:                                        if (incr < 0) {
                   1229:                                                for (reg = 7; reg >= 0; reg--) {
                   1230:                                                        uae_u32 wrd1, wrd2, wrd3;
                   1231:                                                        if (list & 0x80) {
                   1232:                                                                from_exten (regs.fp[reg], &wrd1, &wrd2, &wrd3);
                   1233:                                                                ad -= 4;
                   1234:                                                                x_put_long (ad, wrd3);
                   1235:                                                                ad -= 4;
                   1236:                                                                x_put_long (ad, wrd2);
                   1237:                                                                ad -= 4;
                   1238:                                                                x_put_long (ad, wrd1);
                   1239:                                                        }
                   1240:                                                        list <<= 1;
                   1241:                                                }
                   1242:                                        } else {
                   1243:                                                for (reg = 0; reg <= 7; reg++) {
                   1244:                                                        uae_u32 wrd1, wrd2, wrd3;
                   1245:                                                        if (list & 0x80) {
                   1246:                                                                from_exten (regs.fp[reg], &wrd1, &wrd2, &wrd3);
                   1247:                                                                x_put_long (ad, wrd1);
                   1248:                                                                ad += 4;
                   1249:                                                                x_put_long (ad, wrd2);
                   1250:                                                                ad += 4;
                   1251:                                                                x_put_long (ad, wrd3);
                   1252:                                                                ad += 4;
                   1253:                                                        }
                   1254:                                                        list <<= 1;
                   1255:                                                }
                   1256:                                        }
                   1257:                                        if ((opcode & 0x38) == 0x18)
                   1258:                                                m68k_areg (regs, opcode & 7) = ad;
                   1259:                                        if ((opcode & 0x38) == 0x20)
                   1260:                                                m68k_areg (regs, opcode & 7) = ad;
                   1261:                                } else {
                   1262:                                        /* FMOVEM memory->FPP */
                   1263:                                        if (get_fp_ad (opcode, &ad) == 0) {
                   1264:                                                m68k_setpc (m68k_getpc () - 4);
                   1265:                                                op_illg (opcode);
                   1266:                                                return;
                   1267:                                        }
                   1268:                                        switch ((extra >> 11) & 3) {
                   1269:                case 0: /* static pred */
                   1270:                        list = extra & 0xff;
                   1271:                        incr = -1;
                   1272:                        break;
                   1273:                case 1: /* dynamic pred */
                   1274:                        list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
                   1275:                        incr = -1;
                   1276:                        break;
                   1277:                case 2: /* static postinc */
                   1278:                        list = extra & 0xff;
                   1279:                        incr = 1;
                   1280:                        break;
                   1281:                case 3: /* dynamic postinc */
                   1282:                        list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
                   1283:                        incr = 1;
                   1284:                        break;
                   1285:                                        }
                   1286:                                        if (incr < 0) {
                   1287:                                                for (reg = 7; reg >= 0; reg--) {
                   1288:                                                        uae_u32 wrd1, wrd2, wrd3;
                   1289:                                                        if (list & 0x80) {
                   1290:                                                                ad -= 4;
                   1291:                                                                wrd3 = x_get_long (ad);
                   1292:                                                                ad -= 4;
                   1293:                                                                wrd2 = x_get_long (ad);
                   1294:                                                                ad -= 4;
                   1295:                                                                wrd1 = x_get_long (ad);
                   1296:                                                                regs.fp[reg] = to_exten(wrd1, wrd2, wrd3);
                   1297:                                                        }
                   1298:                                                        list <<= 1;
                   1299:                                                }
                   1300:                                        } else {
                   1301:                                                for (reg = 0; reg <= 7; reg++) {
                   1302:                                                        uae_u32 wrd1, wrd2, wrd3;
                   1303:                                                        if (list & 0x80) {
                   1304:                                                                wrd1 = x_get_long (ad);
                   1305:                                                                ad += 4;
                   1306:                                                                wrd2 = x_get_long (ad);
                   1307:                                                                ad += 4;
                   1308:                                                                wrd3 = x_get_long (ad);
                   1309:                                                                ad += 4;
                   1310:                                                                regs.fp[reg] = to_exten(wrd1, wrd2, wrd3);
                   1311:                                                        }
                   1312:                                                        list <<= 1;
                   1313:                                                }
                   1314:                                        }
                   1315:                                        if ((opcode & 0x38) == 0x18)
                   1316:                                                m68k_areg (regs, opcode & 7) = ad;
                   1317:                                        if ((opcode & 0x38) == 0x20)
                   1318:                                                m68k_areg (regs, opcode & 7) = ad;
                   1319:                                }
                   1320:                        }
                   1321:                        return;
                   1322: 
                   1323:                case 0:
                   1324:                case 2: /* Extremely common */
                   1325:                        reg = (extra >> 7) & 7;
                   1326:                        if ((extra & 0xfc00) == 0x5c00) {
                   1327:                                switch (extra & 0x7f) {
                   1328:                case 0x00:
                   1329:                        regs.fp[reg] = *fp_pi;
                   1330:                        break;
                   1331:                case 0x0b:
                   1332:                        regs.fp[reg] = *fp_l10_2;
                   1333:                        break;
                   1334:                case 0x0c:
                   1335:                        regs.fp[reg] = *fp_exp_1;
                   1336:                        break;
                   1337:                case 0x0d:
                   1338:                        regs.fp[reg] = *fp_l2_e;
                   1339:                        break;
                   1340:                case 0x0e:
                   1341:                        regs.fp[reg] = *fp_l10_e;
                   1342:                        break;
                   1343:                case 0x0f:
                   1344:                        regs.fp[reg] = 0.0;
                   1345:                        break;
                   1346:                case 0x30:
                   1347:                        regs.fp[reg] = *fp_ln_2;
                   1348:                        break;
                   1349:                case 0x31:
                   1350:                        regs.fp[reg] = *fp_ln_10;
                   1351:                        break;
                   1352:                case 0x32:
                   1353:                        regs.fp[reg] = (fptype)fp_1e0;
                   1354:                        break;
                   1355:                case 0x33:
                   1356:                        regs.fp[reg] = (fptype)fp_1e1;
                   1357:                        break;
                   1358:                case 0x34:
                   1359:                        regs.fp[reg] = (fptype)fp_1e2;
                   1360:                        break;
                   1361:                case 0x35:
                   1362:                        regs.fp[reg] = (fptype)fp_1e4;
                   1363:                        break;
                   1364:                case 0x36:
                   1365:                        regs.fp[reg] = (fptype)fp_1e8;
                   1366:                        break;
                   1367:                case 0x37:
                   1368:                        regs.fp[reg] = *fp_1e16;
                   1369:                        break;
                   1370:                case 0x38:
                   1371:                        regs.fp[reg] = *fp_1e32;
                   1372:                        break;
                   1373:                case 0x39:
                   1374:                        regs.fp[reg] = *fp_1e64;
                   1375:                        break;
                   1376:                case 0x3a:
                   1377:                        regs.fp[reg] = *fp_1e128;
                   1378:                        break;
                   1379:                case 0x3b:
                   1380:                        regs.fp[reg] = *fp_1e256;
                   1381:                        break;
                   1382:                case 0x3c:
                   1383:                        regs.fp[reg] = *fp_1e512;
                   1384:                        break;
                   1385:                case 0x3d:
                   1386:                        regs.fp[reg] = *fp_1e1024;
                   1387:                        break;
                   1388:                case 0x3e:
                   1389:                        regs.fp[reg] = *fp_1e2048;
                   1390:                        break;
                   1391:                case 0x3f:
                   1392:                        regs.fp[reg] = *fp_1e4096;
                   1393:                        break;
                   1394:                default:
                   1395:                        m68k_setpc (m68k_getpc () - 4);
                   1396:                        op_illg (opcode);
                   1397:                        return;
                   1398:                                }
                   1399:                                MAKE_FPSR (regs.fp[reg]);
                   1400:                                return;
                   1401:                        }
                   1402:                        if (get_fp_value (opcode, extra, &src) == 0) {
                   1403:                                m68k_setpc (m68k_getpc () - 4);
                   1404:                                op_illg (opcode);
                   1405:                                return;
                   1406:                        }
                   1407: 
                   1408:                        switch (extra & 0x7f) {
                   1409: 
                   1410:                case 0x00: /* FMOVE */
                   1411:                case 0x40: /* Explicit rounding. This is just a quick fix. */
                   1412:                case 0x44: /* Same for all other cases that have three choices */
                   1413:                        regs.fp[reg] = src;        /* Brian King was here. */
                   1414:                        /*<ea> to register needs FPSR updated. See Motorola 68K Manual. */
                   1415:                        if ((extra & 0x44) == 0x40)
                   1416:                                fround (reg);
                   1417:                        break;
                   1418:                case 0x01: /* FINT */
                   1419:                        /* need to take the current rounding mode into account */
                   1420: #if defined(X86_MSVC_ASSEMBLY)
                   1421:                        {
                   1422:                                fptype tmp_fp;
                   1423: 
                   1424:                                __asm {
                   1425:                                        fld  LDPTR src
                   1426:                                                frndint
                   1427:                                                fstp LDPTR tmp_fp
                   1428:                                }
                   1429:                                regs.fp[reg] = tmp_fp;
                   1430:                        }
                   1431: #else /* no X86_MSVC */
                   1432:                        switch ((regs.fpcr >> 4) & 3) {
                   1433:                case 0: /* to nearest */
                   1434:                        regs.fp[reg] = floor (src + 0.5);
                   1435:                        break;
                   1436:                case 1: /* to zero */
                   1437:                        if (src >= 0.0)
                   1438:                                regs.fp[reg] = floor (src);
                   1439:                        else
                   1440:                                regs.fp[reg] = ceil (src);
                   1441:                        break;
                   1442:                case 2: /* down */
                   1443:                        regs.fp[reg] = floor (src);
                   1444:                        break;
                   1445:                case 3: /* up */
                   1446:                        regs.fp[reg] = ceil (src);
                   1447:                        break;
                   1448:                default: /* never reached */
                   1449:                        regs.fp[reg] = src;
                   1450:                        }
                   1451: #endif /* X86_MSVC */
                   1452:                        break;
                   1453:                case 0x02: /* FSINH */
                   1454:                        regs.fp[reg] = sinh (src);
                   1455:                        break;
                   1456:                case 0x03: /* FINTRZ */
                   1457:                        regs.fp[reg] = fp_round_to_zero(src);
                   1458:                        break;
                   1459:                case 0x04: /* FSQRT */
                   1460:                case 0x41:
                   1461:                case 0x45:
                   1462:                        regs.fp[reg] = sqrt (src);
                   1463:                        if ((extra & 0x44) == 0x40)
                   1464:                                fround (reg);
                   1465:                        break;
                   1466:                case 0x06: /* FLOGNP1 */
                   1467:                        regs.fp[reg] = log (src + 1.0);
                   1468:                        break;
                   1469:                case 0x08: /* FETOXM1 */
                   1470:                        regs.fp[reg] = exp (src) - 1.0;
                   1471:                        break;
                   1472:                case 0x09: /* FTANH */
                   1473:                        regs.fp[reg] = tanh (src);
                   1474:                        break;
                   1475:                case 0x0a: /* FATAN */
                   1476:                        regs.fp[reg] = atan (src);
                   1477:                        break;
                   1478:                case 0x0c: /* FASIN */
                   1479:                        regs.fp[reg] = asin (src);
                   1480:                        break;
                   1481:                case 0x0d: /* FATANH */
                   1482: #if 1  /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */
                   1483:                        regs.fp[reg] = 0.5 * log ((1 + src) / (1 - src));
                   1484: #else
                   1485:                        regs.fp[reg] = atanh (src);
                   1486: #endif
                   1487:                        break;
                   1488:                case 0x0e: /* FSIN */
                   1489:                        regs.fp[reg] = sin (src);
                   1490:                        break;
                   1491:                case 0x0f: /* FTAN */
                   1492:                        regs.fp[reg] = tan (src);
                   1493:                        break;
                   1494:                case 0x10: /* FETOX */
                   1495:                        regs.fp[reg] = exp (src);
                   1496:                        break;
                   1497:                case 0x11: /* FTWOTOX */
                   1498:                        regs.fp[reg] = pow (2.0, src);
                   1499:                        break;
                   1500:                case 0x12: /* FTENTOX */
                   1501:                        regs.fp[reg] = pow (10.0, src);
                   1502:                        break;
                   1503:                case 0x14: /* FLOGN */
                   1504:                        regs.fp[reg] = log (src);
                   1505:                        break;
                   1506:                case 0x15: /* FLOG10 */
                   1507:                        regs.fp[reg] = log10 (src);
                   1508:                        break;
                   1509:                case 0x16: /* FLOG2 */
                   1510:                        regs.fp[reg] = *fp_l2_e * log (src);
                   1511:                        break;
                   1512:                case 0x18: /* FABS */
                   1513:                case 0x58:
                   1514:                case 0x5c:
                   1515:                        regs.fp[reg] = src < 0 ? -src : src;
                   1516:                        if ((extra & 0x44) == 0x40)
                   1517:                                fround (reg);
                   1518:                        break;
                   1519:                case 0x19: /* FCOSH */
                   1520:                        regs.fp[reg] = cosh (src);
                   1521:                        break;
                   1522:                case 0x1a: /* FNEG */
                   1523:                case 0x5a:
                   1524:                case 0x5e:
                   1525:                        regs.fp[reg] = -src;
                   1526:                        if ((extra & 0x44) == 0x40)
                   1527:                                fround (reg);
                   1528:                        break;
                   1529:                case 0x1c: /* FACOS */
                   1530:                        regs.fp[reg] = acos (src);
                   1531:                        break;
                   1532:                case 0x1d: /* FCOS */
                   1533:                        regs.fp[reg] = cos (src);
                   1534:                        break;
                   1535:                case 0x1e: /* FGETEXP */
                   1536:                        {
                   1537:                                if (src == 0) {
                   1538:                                        regs.fp[reg] = 0;
                   1539:                                } else {
                   1540:                                        int expon;
                   1541:                                        frexp (src, &expon);
                   1542:                                        regs.fp[reg] = (double) (expon - 1);
                   1543:                                }
                   1544:                        }
                   1545:                        break;
                   1546:                case 0x1f: /* FGETMAN */
                   1547:                        {
                   1548:                                if (src == 0) {
                   1549:                                        regs.fp[reg] = 0;
                   1550:                                } else {
                   1551:                                        int expon;
                   1552:                                        regs.fp[reg] = frexp (src, &expon) * 2.0;
                   1553:                                }
                   1554:                        }
                   1555:                        break;
                   1556:                case 0x20: /* FDIV */
                   1557:                case 0x60:
                   1558:                case 0x64:
                   1559:                        regs.fp[reg] /= src;
                   1560:                        if ((extra & 0x44) == 0x40)
                   1561:                                fround (reg);
                   1562:                        break;
                   1563:                case 0x21: /* FMOD */
                   1564:                        {
                   1565:                                fptype quot = fp_round_to_zero(regs.fp[reg] / src);
                   1566:                                regs.fp[reg] = regs.fp[reg] - quot * src;
                   1567:                        }
                   1568:                        break;
                   1569:                case 0x22: /* FADD */
                   1570:                case 0x62:
                   1571:                case 0x66:
                   1572:                        regs.fp[reg] += src;
                   1573:                        if ((extra & 0x44) == 0x40)
                   1574:                                fround (reg);
                   1575:                        break;
                   1576:                case 0x23: /* FMUL */
                   1577:                case 0x63:
                   1578:                case 0x67:
                   1579:                        regs.fp[reg] *= src;
                   1580:                        if ((extra & 0x44) == 0x40)
                   1581:                                fround (reg);
                   1582:                        break;
                   1583:                case 0x24: /* FSGLDIV */
                   1584:                        regs.fp[reg] /= src;
                   1585:                        break;
                   1586:                case 0x25: /* FREM */
                   1587:                        {
                   1588:                                fptype quot = fp_round_to_nearest(regs.fp[reg] / src);
                   1589:                                regs.fp[reg] = regs.fp[reg] - quot * src;
                   1590:                        }
                   1591:                        break;
                   1592:                case 0x26: /* FSCALE */
                   1593:                        if (src != 0) {
                   1594: #ifdef ldexp
                   1595:                                regs.fp[reg] = ldexp (regs.fp[reg], (int) src);
                   1596: #else
                   1597:                                regs.fp[reg] *= exp (*fp_ln_2 * (int) src);
                   1598: #endif
                   1599:                        }
                   1600:                        break;
                   1601:                case 0x27: /* FSGLMUL */
                   1602:                        regs.fp[reg] *= src;
                   1603:                        break;
                   1604:                case 0x28: /* FSUB */
                   1605:                case 0x68:
                   1606:                case 0x6c:
                   1607:                        regs.fp[reg] -= src;
                   1608:                        if ((extra & 0x44) == 0x40)
                   1609:                                fround (reg);
                   1610:                        break;
                   1611:                case 0x30: /* FSINCOS */
                   1612:                case 0x31:
                   1613:                case 0x32:
                   1614:                case 0x33:
                   1615:                case 0x34:
                   1616:                case 0x35:
                   1617:                case 0x36:
                   1618:                case 0x37:
                   1619:                        regs.fp[extra & 7] = cos (src);
                   1620:                        regs.fp[reg] = sin (src);
                   1621:                        break;
                   1622:                case 0x38: /* FCMP */
                   1623:                        {
                   1624:                                fptype tmp = regs.fp[reg] - src;
                   1625:                                regs.fpsr = 0;
                   1626:                                MAKE_FPSR (tmp);
                   1627:                        }
                   1628:                        return;
                   1629:                case 0x3a: /* FTST */
                   1630:                        regs.fpsr = 0;
                   1631:                        MAKE_FPSR (src);
                   1632:                        return;
                   1633:                default:
                   1634:                        m68k_setpc (m68k_getpc () - 4);
                   1635:                        op_illg (opcode);
                   1636:                        return;
                   1637:                        }
                   1638:                        MAKE_FPSR (regs.fp[reg]);
                   1639:                        return;
                   1640:        }
                   1641:        m68k_setpc (m68k_getpc () - 4);
                   1642:        op_illg (opcode);
                   1643: }
                   1644: 
                   1645: void fpu_reset (void)
                   1646: {
                   1647:        regs.fpcr = regs.fpsr = regs.fpiar = 0;
                   1648:        regs.fp_result = 1;
                   1649:        fpux_restore (NULL);
                   1650: }
                   1651: 
                   1652: uae_u8 *restore_fpu (uae_u8 *src)
                   1653: {
                   1654:        int i;
                   1655:        uae_u32 flags;
                   1656: 
                   1657:        changed_prefs.fpu_model = currprefs.fpu_model = restore_u32 ();
                   1658:        flags = restore_u32 ();
                   1659:        for (i = 0; i < 8; i++) {
                   1660:                uae_u32 w1 = restore_u32 ();
                   1661:                uae_u32 w2 = restore_u32 ();
                   1662:                uae_u32 w3 = restore_u16 ();
                   1663:                regs.fp[i] = to_exten (w1, w2, w3);
                   1664:        }
                   1665:        regs.fpcr = restore_u32 ();
                   1666:        native_set_fpucw (regs.fpcr);
                   1667:        regs.fpsr = restore_u32 ();
                   1668:        regs.fpiar = restore_u32 ();
                   1669:        if (flags & 0x80000000) {
                   1670:                restore_u32();
                   1671:                restore_u32();
                   1672:        }
                   1673:        write_log ("FPU: %d\n", currprefs.fpu_model);
                   1674:        return src;
                   1675: }
                   1676: 
                   1677: uae_u8 *save_fpu (int *len, uae_u8 *dstptr)
                   1678: {
                   1679:        uae_u8 *dstbak,*dst;
                   1680:        int i;
                   1681: 
                   1682:        *len = 0;
                   1683:        if (currprefs.fpu_model == 0)
                   1684:                return 0;
                   1685:        if (dstptr)
                   1686:                dstbak = dst = dstptr;
                   1687:        else
                   1688:                dstbak = dst = xmalloc (uae_u8, 4+4+8*10+4+4+4+4+4);
                   1689:        save_u32 (currprefs.fpu_model);
                   1690:        save_u32 (0x80000000);
                   1691:        for (i = 0; i < 8; i++) {
                   1692:                uae_u32 w1, w2, w3;
                   1693:                from_exten (regs.fp[i], &w1, &w2, &w3);
                   1694:                save_u32 (w1);
                   1695:                save_u32 (w2);
                   1696:                save_u16 (w3);
                   1697:        }
                   1698:        save_u32 (regs.fpcr);
                   1699:        save_u32 (regs.fpsr);
                   1700:        save_u32 (regs.fpiar);
                   1701:        save_u32 (-1);
                   1702:        save_u32 (0);
                   1703:        *len = dst - dstbak;
                   1704:        return dstbak;
                   1705: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.