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

1.1       root        1: /*
                      2: * UAE - The Un*x Amiga Emulator
                      3: *
1.1.1.4   root        4: * MC68881/68882/68040/68060 FPU emulation
1.1       root        5: *
                      6: * Copyright 1996 Herman ten Brugge
                      7: * Modified 2005 Peter Keunecke
1.1.1.4   root        8: * 68040+ exceptions and more by Toni Wilen
1.1       root        9: */
                     10: 
                     11: #define __USE_ISOC9X  /* We might be able to pick up a NaN */
                     12: 
1.1.1.6 ! root       13: #define FPU_TEST 0
        !            14: 
1.1       root       15: #include <math.h>
                     16: #include <float.h>
1.1.1.4   root       17: #include <fenv.h>
                     18: 
                     19: #include "main.h"
                     20: #include "hatari-glue.h"
                     21: 
1.1       root       22: #include "sysconfig.h"
                     23: #include "sysdeps.h"
                     24: 
                     25: #include "options_cpu.h"
                     26: #include "memory.h"
1.1.1.5   root       27: #include "uae/attributes.h"
                     28: #include "uae/vm.h"
1.1       root       29: #include "custom.h"
                     30: #include "events.h"
                     31: #include "newcpu.h"
1.1.1.6 ! root       32: #include "fpp.h"
1.1       root       33: #include "savestate.h"
                     34: #include "cpu_prefetch.h"
                     35: #include "cpummu.h"
1.1.1.4   root       36: #include "cpummu030.h"
                     37: //#include "debug.h"
                     38: 
1.1.1.6 ! root       39: #include "softfloat/softfloat.h"
        !            40: 
        !            41: FPP_PRINT fpp_print;
        !            42: 
        !            43: FPP_IS fpp_is_snan;
        !            44: FPP_IS fpp_unset_snan;
        !            45: FPP_IS fpp_is_nan;
        !            46: FPP_IS fpp_is_infinity;
        !            47: FPP_IS fpp_is_zero;
        !            48: FPP_IS fpp_is_neg;
        !            49: FPP_IS fpp_is_denormal;
        !            50: FPP_IS fpp_is_unnormal;
        !            51: 
        !            52: FPP_GET_STATUS fpp_get_status;
        !            53: FPP_CLEAR_STATUS fpp_clear_status;
        !            54: FPP_SET_MODE fpp_set_mode;
        !            55: 
        !            56: FPP_FROM_NATIVE fpp_from_native;
        !            57: FPP_TO_NATIVE fpp_to_native;
        !            58: 
        !            59: FPP_TO_INT fpp_to_int;
        !            60: FPP_FROM_INT fpp_from_int;
        !            61: 
        !            62: FPP_PACK fpp_to_pack;
        !            63: FPP_PACK fpp_from_pack;
        !            64: 
        !            65: FPP_TO_SINGLE fpp_to_single;
        !            66: FPP_FROM_SINGLE fpp_from_single;
        !            67: FPP_TO_DOUBLE fpp_to_double;
        !            68: FPP_FROM_DOUBLE fpp_from_double;
        !            69: FPP_TO_EXTEN fpp_to_exten;
        !            70: FPP_FROM_EXTEN fpp_from_exten;
        !            71: FPP_TO_EXTEN fpp_to_exten_fmovem;
        !            72: FPP_FROM_EXTEN fpp_from_exten_fmovem;
        !            73: 
        !            74: FPP_A fpp_normalize;
        !            75: FPP_DENORMALIZE fpp_denormalize;
        !            76: FPP_A fpp_get_internal_overflow;
        !            77: FPP_A fpp_get_internal_underflow;
        !            78: FPP_A fpp_get_internal_round_all;
        !            79: FPP_A fpp_get_internal_round;
        !            80: FPP_A fpp_get_internal_round_exten;
        !            81: FPP_A fpp_get_internal;
        !            82: FPP_GET32 fpp_get_internal_grs;
        !            83: 
        !            84: FPP_A fpp_round_single;
        !            85: FPP_A fpp_round_double;
        !            86: FPP_A fpp_round32;
        !            87: FPP_A fpp_round64;
        !            88: FPP_AB fpp_int;
        !            89: FPP_AB fpp_sinh;
        !            90: FPP_AB fpp_intrz;
        !            91: FPP_ABP fpp_sqrt;
        !            92: FPP_AB fpp_lognp1;
        !            93: FPP_AB fpp_etoxm1;
        !            94: FPP_AB fpp_tanh;
        !            95: FPP_AB fpp_atan;
        !            96: FPP_AB fpp_atanh;
        !            97: FPP_AB fpp_sin;
        !            98: FPP_AB fpp_asin;
        !            99: FPP_AB fpp_tan;
        !           100: FPP_AB fpp_etox;
        !           101: FPP_AB fpp_twotox;
        !           102: FPP_AB fpp_tentox;
        !           103: FPP_AB fpp_logn;
        !           104: FPP_AB fpp_log10;
        !           105: FPP_AB fpp_log2;
        !           106: FPP_ABP fpp_abs;
        !           107: FPP_AB fpp_cosh;
        !           108: FPP_ABP fpp_neg;
        !           109: FPP_AB fpp_acos;
        !           110: FPP_AB fpp_cos;
        !           111: FPP_AB fpp_getexp;
        !           112: FPP_AB fpp_getman;
        !           113: FPP_ABP fpp_div;
        !           114: FPP_ABQS fpp_mod;
        !           115: FPP_ABP fpp_add;
        !           116: FPP_ABP fpp_mul;
        !           117: FPP_ABQS fpp_rem;
        !           118: FPP_AB fpp_scale;
        !           119: FPP_ABP fpp_sub;
        !           120: FPP_AB fpp_sgldiv;
        !           121: FPP_AB fpp_sglmul;
        !           122: FPP_AB fpp_cmp;
        !           123: FPP_AB fpp_tst;
        !           124: FPP_ABP fpp_move;
1.1.1.4   root      125: 
1.1       root      126: #define DEBUG_FPP 0
1.1.1.6 ! root      127: #define EXCEPTION_FPP 0
1.1       root      128: 
                    129: STATIC_INLINE int isinrom (void)
                    130: {
                    131:        return (munge24 (m68k_getpc ()) & 0xFFF80000) == 0xF80000 && !currprefs.mmu_model;
                    132: }
                    133: 
1.1.1.6 ! root      134: static int warned = 100;
        !           135: 
        !           136: struct fpp_cr_entry {
        !           137:        uae_u32 val[3];
        !           138:        uae_u8 inexact;
        !           139:        uae_s8 rndoff[4];
        !           140: };
        !           141: 
        !           142: static const struct fpp_cr_entry fpp_cr[22] = {
        !           143:        { {0x40000000, 0xc90fdaa2, 0x2168c235}, 1, {0,-1,-1, 0} }, //  0 = pi
        !           144:        { {0x3ffd0000, 0x9a209a84, 0xfbcff798}, 1, {0, 0, 0, 1} }, //  1 = log10(2)
        !           145:        { {0x40000000, 0xadf85458, 0xa2bb4a9a}, 1, {0, 0, 0, 1} }, //  2 = e
        !           146:        { {0x3fff0000, 0xb8aa3b29, 0x5c17f0bc}, 1, {0,-1,-1, 0} }, //  3 = log2(e)
        !           147:        { {0x3ffd0000, 0xde5bd8a9, 0x37287195}, 0, {0, 0, 0, 0} }, //  4 = log10(e)
        !           148:        { {0x00000000, 0x00000000, 0x00000000}, 0, {0, 0, 0, 0} }, //  5 = 0.0
        !           149:        { {0x3ffe0000, 0xb17217f7, 0xd1cf79ac}, 1, {0,-1,-1, 0} }, //  6 = ln(2)
        !           150:        { {0x40000000, 0x935d8ddd, 0xaaa8ac17}, 1, {0,-1,-1, 0} }, //  7 = ln(10)
        !           151:        { {0x3fff0000, 0x80000000, 0x00000000}, 0, {0, 0, 0, 0} }, //  8 = 1e0
        !           152:        { {0x40020000, 0xa0000000, 0x00000000}, 0, {0, 0, 0, 0} }, //  9 = 1e1
        !           153:        { {0x40050000, 0xc8000000, 0x00000000}, 0, {0, 0, 0, 0} }, // 10 = 1e2
        !           154:        { {0x400c0000, 0x9c400000, 0x00000000}, 0, {0, 0, 0, 0} }, // 11 = 1e4
        !           155:        { {0x40190000, 0xbebc2000, 0x00000000}, 0, {0, 0, 0, 0} }, // 12 = 1e8
        !           156:        { {0x40340000, 0x8e1bc9bf, 0x04000000}, 0, {0, 0, 0, 0} }, // 13 = 1e16
        !           157:        { {0x40690000, 0x9dc5ada8, 0x2b70b59e}, 1, {0,-1,-1, 0} }, // 14 = 1e32
        !           158:        { {0x40d30000, 0xc2781f49, 0xffcfa6d5}, 1, {0, 0, 0, 1} }, // 15 = 1e64
        !           159:        { {0x41a80000, 0x93ba47c9, 0x80e98ce0}, 1, {0,-1,-1, 0} }, // 16 = 1e128
        !           160:        { {0x43510000, 0xaa7eebfb, 0x9df9de8e}, 1, {0,-1,-1, 0} }, // 17 = 1e256
        !           161:        { {0x46a30000, 0xe319a0ae, 0xa60e91c7}, 1, {0,-1,-1, 0} }, // 18 = 1e512
        !           162:        { {0x4d480000, 0xc9767586, 0x81750c17}, 1, {0, 0, 0, 1} }, // 19 = 1e1024
        !           163:        { {0x5a920000, 0x9e8b3b5d, 0xc53d5de5}, 1, {0,-1,-1, 0} }, // 20 = 1e2048
        !           164:        { {0x75250000, 0xc4605202, 0x8a20979b}, 1, {0,-1,-1, 0} }  // 21 = 1e4094
        !           165: };
        !           166: 
        !           167: #define FPP_CR_PI       0
        !           168: #define FPP_CR_LOG10_2  1
        !           169: #define FPP_CR_E        2
        !           170: #define FPP_CR_LOG2_E   3
        !           171: #define FPP_CR_LOG10_E  4
        !           172: #define FPP_CR_ZERO     5
        !           173: #define FPP_CR_LN_2     6
        !           174: #define FPP_CR_LN_10    7
        !           175: #define FPP_CR_1E0      8
        !           176: #define FPP_CR_1E1      9
        !           177: #define FPP_CR_1E2      10
        !           178: #define FPP_CR_1E4      11
        !           179: #define FPP_CR_1E8      12
        !           180: #define FPP_CR_1E16     13
        !           181: #define FPP_CR_1E32     14
        !           182: #define FPP_CR_1E64     15
        !           183: #define FPP_CR_1E128    16
        !           184: #define FPP_CR_1E256    17
        !           185: #define FPP_CR_1E512    18
        !           186: #define FPP_CR_1E1024   19
        !           187: #define FPP_CR_1E2048   20
        !           188: #define FPP_CR_1E4096   21
        !           189: 
        !           190: struct fpp_cr_entry_undef {
        !           191:        uae_u32 val[3];
        !           192: };
        !           193: 
        !           194: #define FPP_CR_NUM_SPECIAL_UNDEFINED 10
        !           195: 
        !           196: // 68881 and 68882 have identical undefined fields
        !           197: static const struct fpp_cr_entry_undef fpp_cr_undef[] = {
        !           198:        { {0x40000000, 0x00000000, 0x00000000} },
        !           199:        { {0x40010000, 0xfe000682, 0x00000000} },
        !           200:        { {0x40010000, 0xffc00503, 0x80000000} },
        !           201:        { {0x20000000, 0x7fffffff, 0x00000000} },
        !           202:        { {0x00000000, 0xffffffff, 0xffffffff} },
        !           203:        { {0x3c000000, 0xffffffff, 0xfffff800} },
        !           204:        { {0x3f800000, 0xffffff00, 0x00000000} },
        !           205:        { {0x00010000, 0xf65d8d9c, 0x00000000} },
        !           206:        { {0x7fff0000, 0x001e0000, 0x00000000} },
        !           207:        { {0x43ff0000, 0x000e0000, 0x00000000} },
        !           208:        { {0x407f0000, 0x00060000, 0x00000000} }
        !           209: };
        !           210: 
        !           211: uae_u32 xhex_nan[]   ={0x7fff0000, 0xffffffff, 0xffffffff};
        !           212: 
1.1.1.4   root      213: static bool fpu_mmu_fixup;
1.1       root      214: 
1.1.1.6 ! root      215: /* Floating Point Control Register (FPCR)
        !           216:  *
        !           217:  * Exception Enable Byte
        !           218:  * x--- ---- ---- ----  bit 15: BSUN (branch/set on unordered)
        !           219:  * -x-- ---- ---- ----  bit 14: SNAN (signaling not a number)
        !           220:  * --x- ---- ---- ----  bit 13: OPERR (operand error)
        !           221:  * ---x ---- ---- ----  bit 12: OVFL (overflow)
        !           222:  * ---- x--- ---- ----  bit 11: UNFL (underflow)
        !           223:  * ---- -x-- ---- ----  bit 10: DZ (divide by zero)
        !           224:  * ---- --x- ---- ----  bit 9: INEX 2 (inexact operation)
        !           225:  * ---- ---x ---- ----  bit 8: INEX 1 (inexact decimal input)
        !           226:  *
        !           227:  * Mode Control Byte
        !           228:  * ---- ---- xx-- ----  bits 7 and 6: PREC (rounding precision)
        !           229:  * ---- ---- --xx ----  bits 5 and 4: RND (rounding mode)
        !           230:  * ---- ---- ---- xxxx  bits 3 to 0: all 0
        !           231:  */
        !           232: 
        !           233: #define FPCR_PREC   0x00C0
        !           234: #define FPCR_RND    0x0030
        !           235: 
        !           236: /* Floating Point Status Register (FPSR)
        !           237:  *
        !           238:  * Condition Code Byte
        !           239:  * xxxx ---- ---- ---- ---- ---- ---- ----  bits 31 to 28: all 0
        !           240:  * ---- x--- ---- ---- ---- ---- ---- ----  bit 27: N (negative)
        !           241:  * ---- -x-- ---- ---- ---- ---- ---- ----  bit 26: Z (zero)
        !           242:  * ---- --x- ---- ---- ---- ---- ---- ----  bit 25: I (infinity)
        !           243:  * ---- ---x ---- ---- ---- ---- ---- ----  bit 24: NAN (not a number or unordered)
        !           244:  *
        !           245:  * Quotient Byte (set and reset only by FMOD and FREM)
        !           246:  * ---- ---- x--- ---- ---- ---- ---- ----  bit 23: sign of quotient
        !           247:  * ---- ---- -xxx xxxx ---- ---- ---- ----  bits 22 to 16: 7 least significant bits of quotient
        !           248:  *
        !           249:  * Exception Status Byte
        !           250:  * ---- ---- ---- ---- x--- ---- ---- ----  bit 15: BSUN (branch/set on unordered)
        !           251:  * ---- ---- ---- ---- -x-- ---- ---- ----  bit 14: SNAN (signaling not a number)
        !           252:  * ---- ---- ---- ---- --x- ---- ---- ----  bit 13: OPERR (operand error)
        !           253:  * ---- ---- ---- ---- ---x ---- ---- ----  bit 12: OVFL (overflow)
        !           254:  * ---- ---- ---- ---- ---- x--- ---- ----  bit 11: UNFL (underflow)
        !           255:  * ---- ---- ---- ---- ---- -x-- ---- ----  bit 10: DZ (divide by zero)
        !           256:  * ---- ---- ---- ---- ---- --x- ---- ----  bit 9: INEX 2 (inexact operation)
        !           257:  * ---- ---- ---- ---- ---- ---x ---- ----  bit 8: INEX 1 (inexact decimal input)
        !           258:  *
        !           259:  * Accrued Exception Byte
        !           260:  * ---- ---- ---- ---- ---- ---- x--- ----  bit 7: IOP (invalid operation)
        !           261:  * ---- ---- ---- ---- ---- ---- -x-- ----  bit 6: OVFL (overflow)
        !           262:  * ---- ---- ---- ---- ---- ---- --x- ----  bit 5: UNFL (underflow)
        !           263:  * ---- ---- ---- ---- ---- ---- ---x ----  bit 4: DZ (divide by zero)
        !           264:  * ---- ---- ---- ---- ---- ---- ---- x---  bit 3: INEX (inexact)
        !           265:  * ---- ---- ---- ---- ---- ---- ---- -xxx  bits 2 to 0: all 0
        !           266:  */
        !           267: 
        !           268: #define FPSR_ZEROBITS   0xF0000007
        !           269: 
        !           270: #define FPSR_CC_N       0x08000000
        !           271: #define FPSR_CC_Z       0x04000000
        !           272: #define FPSR_CC_I       0x02000000
        !           273: #define FPSR_CC_NAN     0x01000000
        !           274: 
        !           275: #define FPSR_QUOT_SIGN  0x00800000
        !           276: #define FPSR_QUOT_LSB   0x007F0000
        !           277: 
        !           278: #define FPSR_AE_IOP     0x00000080
        !           279: #define FPSR_AE_OVFL    0x00000040
        !           280: #define FPSR_AE_UNFL    0x00000020
        !           281: #define FPSR_AE_DZ      0x00000010
        !           282: #define FPSR_AE_INEX    0x00000008
        !           283: 
        !           284: static struct {
        !           285:        // 6888x and 68060
        !           286:        uae_u32 ccr;
        !           287:        uae_u32 eo[3];
        !           288:        // 68060
        !           289:        uae_u32 v;
        !           290:        // 68040
        !           291:        uae_u32 fpiarcu;
        !           292:        uae_u32 cmdreg3b;
        !           293:        uae_u32 cmdreg1b;
        !           294:        uae_u32 stag, dtag;
        !           295:        uae_u32 e1, e3, t;
        !           296:        uae_u32 fpt[3];
        !           297:        uae_u32 et[3];
        !           298:        uae_u32 wbt[3];
        !           299:        uae_u32 grs;
        !           300:        uae_u32 wbte15;
        !           301:        uae_u32 wbtm66;
        !           302: } fsave_data;
1.1.1.4   root      303: 
1.1.1.6 ! root      304: static void reset_fsave_data(void)
1.1       root      305: {
1.1.1.6 ! root      306:        int i;
        !           307:        for (i = 0; i < 3; i++) {
        !           308:                fsave_data.eo[i] = 0;
        !           309:                fsave_data.fpt[i] = 0;
        !           310:                fsave_data.et[i] = 0;
        !           311:                fsave_data.wbt[i] = 0;
        !           312:        }
        !           313:        fsave_data.ccr = 0;
        !           314:        fsave_data.v = 0;
        !           315:        fsave_data.fpiarcu = 0;
        !           316:        fsave_data.cmdreg1b = 0;
        !           317:        fsave_data.cmdreg3b = 0;
        !           318:        fsave_data.stag = 0;
        !           319:        fsave_data.dtag = 0;
        !           320:        fsave_data.e1 = 0;
        !           321:        fsave_data.e3 = 0;
        !           322:        fsave_data.t = 0;
        !           323:        fsave_data.wbte15 = 0;
        !           324:        fsave_data.wbtm66 = 0;
        !           325:        fsave_data.grs = 0;
        !           326: }
        !           327: 
        !           328: static uae_u32 get_ftag(fpdata *src, int size)
        !           329: {
        !           330:        if (fpp_is_zero(src)) {
        !           331:                return 1; // ZERO
        !           332:        } else if (fpp_is_unnormal(src) || fpp_is_denormal(src)) {
        !           333:                if (size == 1 || size == 5)
        !           334:                        return 5; // Single/double DENORMAL
        !           335:                return 4; // Extended DENORMAL or UNNORMAL
        !           336:        } else if  (fpp_is_nan(src)) {
        !           337:                return 3; // NAN
        !           338:        } else if (fpp_is_infinity(src)) {
        !           339:                return 2; // INF
        !           340:        }
        !           341:        return 0; // NORMAL
1.1.1.4   root      342: }
1.1       root      343: 
1.1.1.6 ! root      344: STATIC_INLINE bool fp_is_dyadic(uae_u16 extra)
1.1.1.4   root      345: {
1.1.1.6 ! root      346:        return ((extra & 0x30) == 0x20 || (extra & 0x7f) == 0x38);
1.1.1.4   root      347: }
                    348: 
1.1.1.6 ! root      349: static bool fp_exception_pending(bool pre)
1.1.1.4   root      350: {
1.1.1.6 ! root      351:        // first check for pending arithmetic exceptions
        !           352:        if (currprefs.fpu_softfloat) {
        !           353:                if (regs.fp_exp_pend) {
        !           354:                        if (warned > 0) {
        !           355:                                write_log (_T("FPU ARITHMETIC EXCEPTION (%d)\n"), regs.fp_exp_pend);
        !           356:                        }
        !           357:                        regs.fpu_exp_pre = pre;
        !           358:                        Exception(regs.fp_exp_pend);
        !           359:                        if (currprefs.fpu_model != 68882)
        !           360:                                regs.fp_exp_pend = 0;
        !           361:                        return true;
        !           362:                }
        !           363:        }
        !           364:        // no arithmetic exceptions pending, check for unimplemented datatype
        !           365:        if (regs.fp_unimp_pend) {
        !           366:                if (warned > 0) {
        !           367:                        write_log (_T("FPU unimplemented datatype exception (%s)\n"), pre ? _T("pre") : _T("mid/post"));
        !           368:                }
        !           369:                regs.fpu_exp_pre = pre;
        !           370:                Exception(55);
        !           371:                regs.fp_unimp_pend = 0;
        !           372: 
        !           373:                return true;
        !           374:        }
        !           375:        return false;
1.1.1.4   root      376: }
1.1.1.6 ! root      377: 
        !           378: static void fp_unimp_instruction_exception_pending(void)
1.1.1.4   root      379: {
1.1.1.6 ! root      380:        if (regs.fp_unimp_ins) {
        !           381:                if (warned > 0) {
        !           382:                        write_log (_T("FPU UNIMPLEMENTED INSTRUCTION/FPU DISABLED EXCEPTION PC=%08x\n"), M68K_GETPC);
        !           383:                }
        !           384:                regs.fpu_exp_pre = true;
        !           385:                Exception(11);
        !           386:                regs.fp_unimp_ins = false;
        !           387:                regs.fp_unimp_pend = 0;
        !           388:        }
1.1.1.4   root      389: }
                    390: 
1.1.1.6 ! root      391: void fpsr_set_exception(uae_u32 exception)
1.1.1.4   root      392: {
1.1.1.6 ! root      393:        regs.fpsr |= exception;
1.1       root      394: }
                    395: 
1.1.1.6 ! root      396: static uae_u32 fpsr_get_vector(uae_u32 exception)
1.1.1.4   root      397: {
1.1.1.6 ! root      398:        static const int vtable[8] = { 49, 49, 50, 51, 53, 52, 54, 48 };
        !           399:        int i;
        !           400:        exception >>= 8;
        !           401:        for (i = 7; i >= 0; i--) {
        !           402:                if (exception & (1 << i)) {
        !           403:                        return vtable[i];
        !           404:                }
        !           405:        }
        !           406:        return 0;
1.1.1.4   root      407: }
1.1.1.6 ! root      408: 
        !           409: static void fpsr_check_arithmetic_exception(uae_u32 mask, fpdata *src, uae_u32 opcode, uae_u16 extra, uae_u32 ea)
1.1.1.4   root      410: {
1.1.1.6 ! root      411:        if (!currprefs.fpu_softfloat)
        !           412:                return;
        !           413: 
        !           414:        bool nonmaskable;
        !           415:        uae_u32 exception;
        !           416:        // Any exception status bit and matching exception enable bits set?
        !           417:        exception = regs.fpsr & regs.fpcr & 0xff00;
        !           418:        // Add 68040/68060 nonmaskable exceptions
        !           419:        if (currprefs.cpu_model >= 68040 && currprefs.fpu_model)
        !           420:                exception |= regs.fpsr & (FPSR_OVFL | FPSR_UNFL | mask);
        !           421: 
        !           422:        if (exception) {
        !           423:                regs.fp_exp_pend = fpsr_get_vector(exception);
        !           424:                nonmaskable = (regs.fp_exp_pend != fpsr_get_vector(regs.fpsr & regs.fpcr));
        !           425:                if (warned > 0) {
        !           426:                        write_log(_T("FPU %s arithmetic exception pending: FPSR: %08x, FPCR: %04x (vector: %d)!\n"),
        !           427:                                nonmaskable ? _T("nonmaskable") : _T(""), regs.fpsr, regs.fpcr, regs.fp_exp_pend);
        !           428: #if EXCEPTION_FPP == 0
        !           429:                        warned--;
        !           430: #endif 
        !           431:                }
        !           432: 
        !           433:                if (!currprefs.fpu_softfloat) {
        !           434:                        // log message and exit
        !           435:                        regs.fp_exp_pend = 0;
        !           436:                        return;
        !           437:                }
        !           438: 
        !           439:                regs.fp_opword = opcode;
        !           440:                regs.fp_ea = ea;
        !           441: 
        !           442:                // data for FSAVE stack frame
        !           443:                fpdata eo;
        !           444:                uae_u32 opclass = (extra >> 13) & 7;
        !           445: 
        !           446:                reset_fsave_data();
        !           447: 
        !           448:                if (currprefs.fpu_model == 68881 || currprefs.fpu_model == 68882) {
        !           449:                        // fsave data for 68881 and 68882
        !           450: 
        !           451:                        if (opclass == 3) { // 011
        !           452:                                fsave_data.ccr = ((uae_u32)extra << 16) | extra;
        !           453:                        } else { // 000 or 010
        !           454:                                fsave_data.ccr = ((uae_u32)(opcode | 0x0080) << 16) | extra;
        !           455:                        }
        !           456:                        if (regs.fp_exp_pend == 54 || regs.fp_exp_pend == 52 || regs.fp_exp_pend == 50) { // SNAN, OPERR, DZ
        !           457:                                fpp_from_exten_fmovem(src, &fsave_data.eo[0], &fsave_data.eo[1], &fsave_data.eo[2]);
        !           458:                                if (regs.fp_exp_pend == 52 && opclass == 3) { // OPERR from move to integer or packed
        !           459:                                        fsave_data.eo[0] &= 0x4fff0000;
        !           460:                                        fsave_data.eo[1] = fsave_data.eo[2] = 0;
        !           461:                                }
        !           462:                        } else if (regs.fp_exp_pend == 53) { // OVFL
        !           463:                                fpp_get_internal_overflow(&eo);
        !           464:                                fpp_from_exten_fmovem(&eo, &fsave_data.eo[0], &fsave_data.eo[1], &fsave_data.eo[2]);
        !           465:                        } else if (regs.fp_exp_pend == 51) { // UNFL
        !           466:                                fpp_get_internal_underflow(&eo);
        !           467:                                fpp_from_exten_fmovem(&eo, &fsave_data.eo[0], &fsave_data.eo[1], &fsave_data.eo[2]);
        !           468:                        } // else INEX1, INEX2: do nothing
        !           469: 
        !           470:                } else if (currprefs.cpu_model == 68060) {
        !           471:                        // fsave data for 68060
        !           472:                        regs.fpu_exp_state = 2; // 68060 EXCP frame
        !           473:                        fsave_data.v = regs.fp_exp_pend & 7;
        !           474:                        fpp_from_exten_fmovem(src, &fsave_data.eo[0], &fsave_data.eo[1], &fsave_data.eo[2]);
        !           475:                } else {
        !           476:                        // fsave data for 68040
        !           477:                        regs.fpu_exp_state = 1; // 68040 UNIMP frame
        !           478: 
        !           479:                        uae_u32 reg = (extra >> 7) & 7;
        !           480:                        int size = (extra >> 10) & 7;
        !           481: 
        !           482:                        fsave_data.fpiarcu = regs.fpiar;
        !           483: 
        !           484:                        if (regs.fp_exp_pend == 54) { // SNAN (undocumented)
        !           485:                                fsave_data.wbte15 = 1;
        !           486:                                fsave_data.grs = 7;
        !           487:                        } else {
        !           488:                                fsave_data.grs = 1;
        !           489:                        }
        !           490: 
        !           491:                        if (opclass == 3) { // OPCLASS 011
        !           492:                                fsave_data.cmdreg1b = extra;
        !           493:                                fsave_data.e1 = 1;
        !           494:                                fsave_data.t = 1;
        !           495:                                fsave_data.wbte15 = (regs.fp_exp_pend == 51 || regs.fp_exp_pend == 54) ? 1 : 0; // UNFL, SNAN
        !           496: 
        !           497:                                if (fpp_is_snan(src)) {
        !           498:                                        fpp_unset_snan(src);
        !           499:                                }
        !           500:                                fpp_from_exten_fmovem(src, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]);
        !           501:                                fsave_data.stag = get_ftag(src, -1);
        !           502:                        } else { // OPCLASS 000 and 010
        !           503:                                fsave_data.cmdreg1b = extra;
        !           504:                                fsave_data.e1 = 1;
        !           505:                                fsave_data.wbte15 = (regs.fp_exp_pend == 54) ? 1 : 0; // SNAN (undocumented)
        !           506: 
        !           507:                                if (regs.fp_exp_pend == 51 || regs.fp_exp_pend == 53 || regs.fp_exp_pend == 49) { // UNFL, OVFL, INEX
        !           508:                                        if ((extra & 0x30) == 0x20 || (extra & 0x3f) == 0x04) { // FADD, FSUB, FMUL, FDIV, FSQRT
        !           509:                                                regs.fpu_exp_state = 2; // 68040 BUSY frame
        !           510:                                                fsave_data.e3 = 1;
        !           511:                                                fsave_data.e1 = 0;
        !           512:                                                fsave_data.cmdreg3b = (extra & 0x3C3) | ((extra & 0x038)>>1) | ((extra & 0x004)<<3);
        !           513:                                                if (regs.fp_exp_pend == 51) { // UNFL
        !           514:                                                        fpp_get_internal(&eo);
        !           515:                                                } else { // OVFL, INEX
        !           516:                                                        fpp_get_internal_round(&eo);
        !           517:                                                }
        !           518:                                                fsave_data.grs = fpp_get_internal_grs();
        !           519:                                                fpp_from_exten_fmovem(&eo, &fsave_data.wbt[0], &fsave_data.wbt[1], &fsave_data.wbt[2]);
        !           520:                                                fsave_data.wbte15 = (regs.fp_exp_pend == 51) ? 1 : 0; // UNFL
        !           521:                                                // src and dst is stored (undocumented)
        !           522:                                                fpp_from_exten_fmovem(src, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]);
        !           523:                                                fsave_data.stag = get_ftag(src, (opclass == 0) ? -1 : size);
        !           524:                                                if (fp_is_dyadic(extra)) {
        !           525:                                                        fpp_from_exten_fmovem(&regs.fp[reg], &fsave_data.fpt[0], &fsave_data.fpt[1], &fsave_data.fpt[2]);
        !           526:                                                        fsave_data.dtag = get_ftag(&regs.fp[reg], -1);
        !           527:                                                }
        !           528:                                        } else { // FMOVE to register, FABS, FNEG
        !           529:                                                fpp_get_internal_round_exten(&eo);
        !           530:                                                fsave_data.grs = fpp_get_internal_grs();
        !           531:                                                fpp_from_exten_fmovem(&eo, &fsave_data.fpt[0], &fsave_data.fpt[1], &fsave_data.fpt[2]);
        !           532:                                                fpp_get_internal_round_all(&eo); // weird
        !           533:                                                fpp_from_exten_fmovem(&eo, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]); // undocumented
        !           534:                                                fsave_data.stag = get_ftag(src, (opclass == 0) ? -1 : size);
        !           535:                                        }
        !           536:                                } else { // SNAN, OPERR, DZ
        !           537:                                        fpp_from_exten_fmovem(src, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]);
        !           538:                                        fsave_data.stag = get_ftag(src, (opclass == 0) ? -1 : size);
        !           539:                                        if (fp_is_dyadic(extra)) {
        !           540:                                                fpp_from_exten_fmovem(&regs.fp[reg], &fsave_data.fpt[0], &fsave_data.fpt[1], &fsave_data.fpt[2]);
        !           541:                                                fsave_data.dtag = get_ftag(&regs.fp[reg], -1);
        !           542:                                        }
        !           543:                                }
        !           544:                        }
        !           545:                }
        !           546:        }
1.1.1.4   root      547: }
1.1       root      548: 
1.1.1.6 ! root      549: static void fpsr_set_result(fpdata *result)
1.1       root      550: {
1.1.1.6 ! root      551: #ifdef JIT
        !           552:        regs.fp_result = *result;
1.1       root      553: #endif
1.1.1.6 ! root      554:        // condition code byte
        !           555:        regs.fpsr &= 0x00fffff8; // clear cc
        !           556:        if (fpp_is_nan (result)) {
        !           557:                regs.fpsr |= FPSR_CC_NAN;
        !           558:        } else if (fpp_is_zero(result)) {
        !           559:                regs.fpsr |= FPSR_CC_Z;
        !           560:        } else if (fpp_is_infinity (result)) {
        !           561:                regs.fpsr |= FPSR_CC_I;
        !           562:        }
        !           563:        if (fpp_is_neg(result))
        !           564:                regs.fpsr |= FPSR_CC_N;
1.1.1.4   root      565: }
1.1.1.6 ! root      566: static void fpsr_clear_status(void)
1.1.1.4   root      567: {
1.1.1.6 ! root      568:        // clear exception status byte only
        !           569:        regs.fpsr &= 0x0fff00f8;
        !           570:        
        !           571:        // clear external status
        !           572:        fpp_clear_status();
1.1.1.4   root      573: }
1.1.1.6 ! root      574: 
        !           575: static uae_u32 fpsr_make_status(void)
1.1.1.4   root      576: {
1.1.1.6 ! root      577:        uae_u32 exception;
        !           578: 
        !           579:        // get external status
        !           580:        fpp_get_status(&regs.fpsr);
        !           581:        
        !           582:        // update accrued exception byte
        !           583:        if (regs.fpsr & (FPSR_BSUN | FPSR_SNAN | FPSR_OPERR))
        !           584:                regs.fpsr |= FPSR_AE_IOP;  // IOP = BSUN || SNAN || OPERR
        !           585:        if (regs.fpsr & FPSR_OVFL)
        !           586:                regs.fpsr |= FPSR_AE_OVFL; // OVFL = OVFL
        !           587:        if ((regs.fpsr & FPSR_UNFL) && (regs.fpsr & FPSR_INEX2))
        !           588:                regs.fpsr |= FPSR_AE_UNFL; // UNFL = UNFL && INEX2
        !           589:        if (regs.fpsr & FPSR_DZ)
        !           590:                regs.fpsr |= FPSR_AE_DZ;   // DZ = DZ
        !           591:        if (regs.fpsr & (FPSR_OVFL | FPSR_INEX2 | FPSR_INEX1))
        !           592:                regs.fpsr |= FPSR_AE_INEX; // INEX = INEX1 || INEX2 || OVFL
        !           593:        
        !           594:        if (!currprefs.fpu_softfloat)
        !           595:                return 0;
        !           596: 
        !           597:        // return exceptions that interrupt calculation
        !           598:        exception = regs.fpsr & regs.fpcr & (FPSR_SNAN | FPSR_OPERR | FPSR_DZ);
        !           599:        if (currprefs.cpu_model >= 68040 && currprefs.fpu_model)
        !           600:                exception |= regs.fpsr & (FPSR_OVFL | FPSR_UNFL);
        !           601: 
        !           602:        return exception;
1.1.1.4   root      603: }
1.1.1.6 ! root      604: 
        !           605: static int fpsr_set_bsun(void)
1.1.1.4   root      606: {
1.1.1.6 ! root      607:        regs.fpsr |= FPSR_BSUN;
        !           608:        regs.fpsr |= FPSR_AE_IOP;
        !           609:        
        !           610:        if (regs.fpcr & FPSR_BSUN) {
        !           611:                // logging only so far
        !           612:                write_log (_T("FPU exception: BSUN! (FPSR: %08x, FPCR: %04x)\n"), regs.fpsr, regs.fpcr);
        !           613:                if (currprefs.fpu_softfloat) {
        !           614:                        regs.fp_exp_pend = fpsr_get_vector(FPSR_BSUN);
        !           615:                        fp_exception_pending(true);
        !           616:                        return 1;
        !           617:                }
        !           618:        }
        !           619:        return 0;
1.1.1.4   root      620: }
1.1.1.6 ! root      621: 
        !           622: static void fpsr_set_quotient(uae_u64 quot, uae_u8 sign)
1.1.1.4   root      623: {
1.1.1.6 ! root      624:        regs.fpsr &= 0x0f00fff8;
        !           625:        regs.fpsr |= (quot << 16) & FPSR_QUOT_LSB;
        !           626:        regs.fpsr |= sign ? FPSR_QUOT_SIGN : 0;
1.1.1.4   root      627: }
1.1.1.6 ! root      628: static void fpsr_get_quotient(uae_u64 *quot, uae_u8 *sign)
1.1.1.4   root      629: {
1.1.1.6 ! root      630:        *quot = (regs.fpsr & FPSR_QUOT_LSB) >> 16;
        !           631:        *sign = (regs.fpsr & FPSR_QUOT_SIGN) ? 1 : 0;
1.1       root      632: }
                    633: 
1.1.1.6 ! root      634: uae_u32 fpp_get_fpsr (void)
1.1       root      635: {
1.1.1.6 ! root      636: #ifdef JIT
        !           637:        if (currprefs.cachesize && currprefs.compfpu) {
        !           638:                regs.fpsr &= 0x00fffff8; // clear cc
        !           639:                if (fpp_is_nan (&regs.fp_result)) {
        !           640:                        regs.fpsr |= FPSR_CC_NAN;
        !           641:                } else if (fpp_is_zero(&regs.fp_result)) {
        !           642:                        regs.fpsr |= FPSR_CC_Z;
        !           643:                } else if (fpp_is_infinity (&regs.fp_result)) {
        !           644:                        regs.fpsr |= FPSR_CC_I;
        !           645:                }
        !           646:                if (fpp_is_neg(&regs.fp_result))
        !           647:                        regs.fpsr |= FPSR_CC_N;
1.1       root      648:        }
1.1.1.4   root      649: #endif
1.1.1.6 ! root      650:        return regs.fpsr;
        !           651: }
1.1       root      652: 
1.1.1.6 ! root      653: static void fpp_set_fpcr (uae_u32 val)
1.1       root      654: {
1.1.1.6 ! root      655:        fpp_set_mode(val);
        !           656:        regs.fpcr = val & 0xffff;
1.1       root      657: }
                    658: 
1.1.1.6 ! root      659: static void fpnan (fpdata *fpd)
1.1.1.4   root      660: {
1.1.1.6 ! root      661:        fpp_to_exten(fpd, xhex_nan[0], xhex_nan[1], xhex_nan[2]);
1.1.1.4   root      662: }
                    663: 
1.1.1.6 ! root      664: static void fpclear (fpdata *fpd)
1.1.1.4   root      665: {
1.1.1.6 ! root      666:        fpp_from_int(fpd, 0);
1.1.1.4   root      667: }
1.1.1.6 ! root      668: static void fpset (fpdata *fpd, uae_s32 val)
1.1.1.5   root      669: {
1.1.1.6 ! root      670:        fpp_from_int(fpd, val);
1.1.1.5   root      671: }
                    672: 
1.1.1.6 ! root      673: static void fpp_set_fpsr (uae_u32 val)
1.1.1.5   root      674: {
1.1.1.6 ! root      675:        regs.fpsr = val;
        !           676: 
        !           677: #ifdef JIT
        !           678:        // check comment in fpp_cond
        !           679:        if (currprefs.cachesize && currprefs.compfpu) {
        !           680:                if (val & 0x01000000)
        !           681:                        fpnan(&regs.fp_result);
        !           682:                else if (val & 0x04000000)
        !           683:                        fpset(&regs.fp_result, 0);
        !           684:                else if (val & 0x08000000)
        !           685:                        fpset(&regs.fp_result, -1);
        !           686:                else
        !           687:                        fpset(&regs.fp_result, 1);
1.1.1.5   root      688:        }
1.1.1.4   root      689: #endif
1.1.1.5   root      690: }
                    691: 
1.1.1.6 ! root      692: bool fpu_get_constant(fpdata *fpd, int cr)
1.1.1.5   root      693: {
1.1.1.6 ! root      694:        uae_u32 f[3] = { 0, 0, 0 };
        !           695:        int entry = 0;
        !           696:        bool round = true;
        !           697:        int mode = (regs.fpcr >> 4) & 3;
        !           698:        int prec = (regs.fpcr >> 6) & 3;
        !           699:        
        !           700:        switch (cr)
        !           701:        {
        !           702:                case 0x00: // pi
        !           703:                        entry = FPP_CR_PI;
        !           704:                        break;
        !           705:                case 0x0b: // log10(2)
        !           706:                        entry = FPP_CR_LOG10_2;
        !           707:                        break;
        !           708:                case 0x0c: // e
        !           709:                        entry = FPP_CR_E;
        !           710:                        break;
        !           711:                case 0x0d: // log2(e)
        !           712:                        entry = FPP_CR_LOG2_E;
        !           713:                        break;
        !           714:                case 0x0e: // log10(e)
        !           715:                        entry = FPP_CR_LOG10_E;
        !           716:                        break;
        !           717:                case 0x0f: // 0.0
        !           718:                        entry = FPP_CR_ZERO;
        !           719:                        break;
        !           720:                case 0x30: // ln(2)
        !           721:                        entry = FPP_CR_LN_2;
        !           722:                        break;
        !           723:                case 0x31: // ln(10)
        !           724:                        entry = FPP_CR_LN_10;
        !           725:                        break;
        !           726:                case 0x32: // 1e0
        !           727:                        entry = FPP_CR_1E0;
        !           728:                        break;
        !           729:                case 0x33: // 1e1
        !           730:                        entry = FPP_CR_1E1;
        !           731:                        break;
        !           732:                case 0x34: // 1e2
        !           733:                        entry = FPP_CR_1E2;
        !           734:                        break;
        !           735:                case 0x35: // 1e4
        !           736:                        entry = FPP_CR_1E4;
        !           737:                        break;
        !           738:                case 0x36: // 1e8
        !           739:                        entry = FPP_CR_1E8;
        !           740:                        break;
        !           741:                case 0x37: // 1e16
        !           742:                        entry = FPP_CR_1E16;
        !           743:                        break;
        !           744:                case 0x38: // 1e32
        !           745:                        entry = FPP_CR_1E32;
        !           746:                        break;
        !           747:                case 0x39: // 1e64
        !           748:                        entry = FPP_CR_1E64;
        !           749:                        break;
        !           750:                case 0x3a: // 1e128
        !           751:                        entry = FPP_CR_1E128;
        !           752:                        break;
        !           753:                case 0x3b: // 1e256
        !           754:                        entry = FPP_CR_1E256;
        !           755:                        break;
        !           756:                case 0x3c: // 1e512
        !           757:                        entry = FPP_CR_1E512;
        !           758:                        break;
        !           759:                case 0x3d: // 1e1024
        !           760:                        entry = FPP_CR_1E1024;
        !           761:                        break;
        !           762:                case 0x3e: // 1e2048
        !           763:                        entry = FPP_CR_1E2048;
        !           764:                        break;
        !           765:                case 0x3f: // 1e4096
        !           766:                        entry = FPP_CR_1E4096;
        !           767:                        break;
        !           768:                default: // undefined
        !           769:                {
        !           770:                        bool check_f1_adjust = false;
        !           771:                        int f1_adjust = 0;
        !           772:                        uae_u32 sr = 0;
        !           773: 
        !           774:                        if (cr > FPP_CR_NUM_SPECIAL_UNDEFINED) {
        !           775:                                cr = 0; // Most undefined fields contain this
        !           776:                        }
        !           777:                        f[0] = fpp_cr_undef[cr].val[0];
        !           778:                        f[1] = fpp_cr_undef[cr].val[1];
        !           779:                        f[2] = fpp_cr_undef[cr].val[2];
        !           780:                        // Rounding mode and precision works very strangely here..
        !           781:                        switch (cr)
        !           782:                        {
        !           783:                                case 1:
        !           784:                                check_f1_adjust = true;
        !           785:                                break;
        !           786:                                case 2:
        !           787:                                if (prec == 1 && mode == 3)
        !           788:                                        f1_adjust = -1;
        !           789:                                break;
        !           790:                                case 3:
        !           791:                                if (prec == 1 && (mode == 0 || mode == 3))
        !           792:                                        sr |= FPSR_CC_I;
        !           793:                                else
        !           794:                                        sr |= FPSR_CC_NAN;
        !           795:                                break;
        !           796:                                case 7:
        !           797:                                sr |= FPSR_CC_NAN;
        !           798:                                check_f1_adjust = true;
        !           799:                                break;
        !           800:                        }
        !           801:                        if (check_f1_adjust) {
        !           802:                                if (prec == 1) {
        !           803:                                        if (mode == 0) {
        !           804:                                                f1_adjust = -1;
        !           805:                                        } else if (mode == 1 || mode == 2) {
        !           806:                                                f1_adjust = 1;
        !           807:                                        }
        !           808:                                }
        !           809:                        }
        !           810:                        fpp_to_exten_fmovem(fpd, f[0], f[1], f[2]);
        !           811:                        if (prec == 1)
        !           812:                                fpp_round32(fpd);
        !           813:                        if (prec >= 2)
        !           814:                                fpp_round64(fpd);
        !           815: 
        !           816:                        if (f1_adjust) {
        !           817:                                fpp_from_exten_fmovem(fpd, &f[0], &f[1], &f[2]);
        !           818:                                f[1] += f1_adjust * 0x80;
        !           819:                                fpp_to_exten_fmovem(fpd, f[0], f[1], f[2]);
        !           820:                        }
        !           821: 
        !           822:                        fpsr_set_result(fpd);
        !           823:                        regs.fpsr |= sr;
        !           824:                        return false;
        !           825:                }
1.1.1.5   root      826:        }
1.1       root      827: 
1.1.1.6 ! root      828:        f[0] = fpp_cr[entry].val[0];
        !           829:        f[1] = fpp_cr[entry].val[1];
        !           830:        f[2] = fpp_cr[entry].val[2];
        !           831:        // if constant is inexact, set inexact bit and round
        !           832:        // note: with valid constants, LSB never wraps
        !           833:        if (fpp_cr[entry].inexact) {
        !           834:                fpsr_set_exception(FPSR_INEX2);
        !           835:                f[2] += fpp_cr[entry].rndoff[mode];
        !           836:        }
1.1       root      837: 
1.1.1.6 ! root      838:        fpp_to_exten_fmovem(fpd, f[0], f[1], f[2]);
        !           839:        
        !           840:        if (prec == 1)
        !           841:                fpp_round32(fpd);
        !           842:        if (prec >= 2)
        !           843:                fpp_round64(fpd);
        !           844:        
        !           845:        fpsr_set_result(fpd);
        !           846: 
        !           847:        return true;
        !           848: }
        !           849: 
        !           850: #if 0
1.1.1.4   root      851: static void fpu_format_error (void)
1.1       root      852: {
1.1.1.4   root      853:        uaecptr newpc;
                    854:        regs.t0 = regs.t1 = 0;
                    855:        MakeSR ();
                    856:        if (!regs.s) {
                    857:                regs.usp = m68k_areg (regs, 7);
                    858:                m68k_areg (regs, 7) = regs.isp;
                    859:        }
                    860:        regs.s = 1;
                    861:        m68k_areg (regs, 7) -= 2;
                    862:        x_put_long (m68k_areg (regs, 7), 0x0000 + 14 * 4);
                    863:        m68k_areg (regs, 7) -= 4;
                    864:        x_put_long (m68k_areg (regs, 7), m68k_getpc ());
                    865:        m68k_areg (regs, 7) -= 2;
                    866:        x_put_long (m68k_areg (regs, 7), regs.sr);
                    867:        newpc = x_get_long (regs.vbr + 14 * 4);
                    868:        m68k_setpc (newpc);
                    869: #ifdef JIT
                    870:        set_special (SPCFLAG_END_COMPILE);
1.1.1.2   root      871: #endif
1.1.1.4   root      872:        regs.fp_exception = true;
1.1       root      873: }
1.1.1.6 ! root      874: #endif
1.1       root      875: 
1.1.1.6 ! root      876: static void fp_unimp_instruction(uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr oldpc, fpdata *src, int reg, int size)
        !           877: {
        !           878:        if ((extra & 0x7f) == 4) // FSQRT 4->5
        !           879:                extra |= 1;
1.1.1.4   root      880: 
1.1.1.6 ! root      881:        // data for fsave stack frame
        !           882:        regs.fpu_exp_state = 1; // 68060 IDLE frame, 68040 UNIMP frame
        !           883: 
        !           884:        if (currprefs.cpu_model == 68060) {
        !           885:                // fsave data for 68060
        !           886:                reset_fsave_data();
        !           887:        } else if(currprefs.cpu_model == 68040) {
        !           888:                // fsave data for 68040
        !           889:                fsave_data.fpiarcu = regs.fpiar;
        !           890: 
        !           891:                if (regs.fp_unimp_pend == 0) { // else data has been saved by fp_unimp_datatype
        !           892:                        reset_fsave_data();
        !           893:                        fsave_data.cmdreg3b = (extra & 0x3C3) | ((extra & 0x038) >> 1) | ((extra & 0x004) << 3);
        !           894:                        fsave_data.cmdreg1b = extra;
        !           895:                        fpp_from_exten_fmovem(src, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]);
        !           896:                        fsave_data.stag = get_ftag(src, size);
        !           897:                        if (reg >= 0) {
        !           898:                                fpp_from_exten_fmovem(&regs.fp[reg], &fsave_data.fpt[0], &fsave_data.fpt[1], &fsave_data.fpt[2]);
        !           899:                                fsave_data.dtag = get_ftag(&regs.fp[reg], -1);
        !           900:                        }
1.1.1.4   root      901:                }
                    902:        }
1.1.1.6 ! root      903:        if (warned > 0) {
        !           904:                write_log (_T("FPU unimplemented instruction: OP=%04X-%04X SRC=%08X-%08X-%08X EA=%08X PC=%08X\n"),
        !           905:                        opcode, extra, fsave_data.et[0],fsave_data.et[1],fsave_data.et[2], ea, oldpc);
        !           906:  #if EXCEPTION_FPP == 0
        !           907:                warned--;
        !           908:  #endif
        !           909:        }
        !           910:        
        !           911:        regs.fp_ea = ea;
        !           912:        regs.fp_unimp_ins = true;
        !           913:        fp_unimp_instruction_exception_pending();
        !           914: 
        !           915:        regs.fp_exception = true;
        !           916: 
        !           917: }
        !           918: 
        !           919: static void fp_unimp_datatype(uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr oldpc, fpdata *src, uae_u32 *packed)
        !           920: {
        !           921:        uae_u32 reg = (extra >> 7) & 7;
        !           922:        uae_u32 size = (extra >> 10) & 7;
        !           923:        uae_u32 opclass = (extra >> 13) & 7;
        !           924: 
        !           925:        regs.fp_opword = opcode;
        !           926:        regs.fp_ea = ea;
        !           927:        regs.fp_unimp_pend = packed ? 2 : 1;
        !           928: 
        !           929:        if((extra & 0x7f) == 4) // FSQRT 4->5
        !           930:                extra |= 1;
        !           931: 
        !           932:        // data for fsave stack frame
        !           933:        reset_fsave_data();
        !           934:        regs.fpu_exp_state = 2; // 68060 EXCP frame, 68040 BUSY frame
        !           935: 
1.1.1.4   root      936:        if (currprefs.cpu_model == 68060) {
1.1.1.6 ! root      937:                // fsave data for 68060
        !           938:                if (packed) {
        !           939:                        regs.fpu_exp_state = 1; // 68060 IDLE frame
        !           940:                } else {
        !           941:                        fsave_data.v = 7; // vector & 0x7
        !           942:                        fpp_from_exten_fmovem(src, &fsave_data.eo[0], &fsave_data.eo[1], &fsave_data.eo[2]);
1.1.1.4   root      943:                }
                    944:        } else if (currprefs.cpu_model == 68040) {
1.1.1.6 ! root      945:                // fsave data for 68040
        !           946:                fsave_data.cmdreg1b = extra;
        !           947:                fsave_data.fpiarcu = regs.fpiar;
        !           948:                if (packed) {
        !           949:                        fsave_data.e1 = 1; // used to distinguish packed operands
        !           950:                }
        !           951:                if (opclass == 3) { // OPCLASS 011
        !           952:                        fsave_data.t = 1;
        !           953:                        fpp_from_exten_fmovem(src, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]);
        !           954:                        fsave_data.stag = get_ftag(src, -1);
        !           955:                        fpp_from_exten_fmovem(src, &fsave_data.fpt[0], &fsave_data.fpt[1], &fsave_data.fpt[2]); // undocumented
        !           956:                        fsave_data.dtag = get_ftag(src, -1); // undocumented
        !           957:                } else { // OPCLASS 000 and 010
        !           958:                        if (packed) {
        !           959:                                fsave_data.fpt[2] = packed[0]; // yes, this is correct.
        !           960:                                fsave_data.fpt[1] = packed[1]; // undocumented
        !           961:                                fsave_data.et[1] = packed[1];
        !           962:                                fsave_data.et[2] = packed[2];
        !           963:                                fsave_data.stag = 7; // undocumented
        !           964:                        } else {
        !           965:                                fpp_from_exten_fmovem(src, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]);
        !           966:                                fsave_data.stag = get_ftag(src, (opclass == 0) ? -1 : size);
        !           967:                                if (fsave_data.stag == 5) {
        !           968:                                        fsave_data.et[0] = (size == 1) ? 0x3f800000 : 0x3c000000; // exponent for denormalized single and double
        !           969:                                }
        !           970:                                if (fp_is_dyadic(extra)) {
        !           971:                                        fpp_from_exten_fmovem(&regs.fp[reg], &fsave_data.fpt[0], &fsave_data.fpt[1], &fsave_data.fpt[2]);
        !           972:                                        fsave_data.dtag = get_ftag(&regs.fp[reg], -1);
        !           973:                                }
        !           974:                        }
1.1.1.4   root      975:                }
                    976:        }
                    977:        if (warned > 0) {
1.1.1.6 ! root      978:                write_log (_T("FPU unimplemented datatype (%s): OP=%04X-%04X SRC=%08X-%08X-%08X EA=%08X PC=%08X\n"),
        !           979:                        packed ? "packed" : "denormal", opcode, extra,
        !           980:                        packed ? fsave_data.fpt[2] : fsave_data.et[0], fsave_data.et[1], fsave_data.et[2], ea, oldpc);
1.1.1.4   root      981: #if EXCEPTION_FPP == 0
                    982:                warned--;
                    983: #endif
                    984:        }
                    985:        regs.fp_exception = true;
                    986: }
                    987: 
1.1.1.6 ! root      988: static void fpu_op_illg(uae_u16 opcode, uae_u32 ea, uaecptr oldpc)
1.1.1.4   root      989: {
                    990:        if ((currprefs.cpu_model == 68060 && (currprefs.fpu_model == 0 || (regs.pcr & 2)))
                    991:                || (currprefs.cpu_model == 68040 && currprefs.fpu_model == 0)) {
1.1.1.6 ! root      992:                        regs.fp_unimp_ins  = true;
        !           993:                        regs.fp_ea = ea;
        !           994:                        fp_unimp_instruction_exception_pending();
1.1.1.4   root      995:                        return;
                    996:        }
                    997:        regs.fp_exception = true;
                    998:        m68k_setpc (oldpc);
                    999:        op_illg (opcode);
                   1000: }
                   1001: 
                   1002: static void fpu_noinst (uae_u16 opcode, uaecptr pc)
                   1003: {
                   1004: #if EXCEPTION_FPP
                   1005:        write_log (_T("Unknown FPU instruction %04X %08X\n"), opcode, pc);
                   1006: #endif
                   1007:        regs.fp_exception = true;
                   1008:        m68k_setpc (pc);
                   1009:        op_illg (opcode);
                   1010: }
                   1011: 
1.1.1.6 ! root     1012: static bool if_no_fpu(void)
        !          1013: {
        !          1014:        return (regs.pcr & 2) || currprefs.fpu_model <= 0;
        !          1015: }
        !          1016: 
1.1.1.4   root     1017: static bool fault_if_no_fpu (uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc)
                   1018: {
1.1.1.6 ! root     1019:        if (if_no_fpu()) {
1.1.1.4   root     1020: #if EXCEPTION_FPP
                   1021:                write_log (_T("no FPU: %04X-%04X PC=%08X\n"), opcode, extra, oldpc);
                   1022: #endif
1.1.1.6 ! root     1023:                if (fpu_mmu_fixup) {
        !          1024:                        m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
        !          1025:                        mmufixup[0].reg = -1;
        !          1026: 
        !          1027:                }
        !          1028:                fpu_op_illg(opcode, ea, oldpc);
1.1.1.4   root     1029:                return true;
                   1030:        }
                   1031:        return false;
                   1032: }
                   1033: 
                   1034: static bool fault_if_unimplemented_680x0 (uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *src, int reg)
                   1035: {
                   1036:        if (fault_if_no_fpu (opcode, extra, ea, oldpc))
                   1037:                return true;
                   1038:        if (currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
                   1039:                if ((extra & (0x8000 | 0x2000)) != 0)
                   1040:                        return false;
                   1041:                if ((extra & 0xfc00) == 0x5c00) {
                   1042:                        // FMOVECR
1.1.1.6 ! root     1043:                        fp_unimp_instruction(opcode, extra, ea, oldpc, src, reg, -1);
1.1.1.4   root     1044:                        return true;
                   1045:                }
                   1046:                uae_u16 v = extra & 0x7f;
1.1.1.6 ! root     1047:                /* 68040/68060 only variants. 6888x = F-line exception. */
1.1.1.4   root     1048:                switch (v)
                   1049:                {
1.1.1.6 ! root     1050:                        case 0x00: /* FMOVE */
        !          1051:                        case 0x40: /* FSMOVE */
        !          1052:                        case 0x44: /* FDMOVE */
        !          1053:                        case 0x04: /* FSQRT */
        !          1054:                        case 0x41: /* FSSQRT */
        !          1055:                        case 0x45: /* FDSQRT */
        !          1056:                        case 0x18: /* FABS */
        !          1057:                        case 0x58: /* FSABS */
        !          1058:                        case 0x5c: /* FDABS */
        !          1059:                        case 0x1a: /* FNEG */
        !          1060:                        case 0x5a: /* FSNEG */
        !          1061:                        case 0x5e: /* FDNEG */
        !          1062:                        case 0x20: /* FDIV */
        !          1063:                        case 0x60: /* FSDIV */
        !          1064:                        case 0x64: /* FDDIV */
        !          1065:                        case 0x22: /* FADD */
        !          1066:                        case 0x62: /* FSADD */
        !          1067:                        case 0x66: /* FDADD */
        !          1068:                        case 0x23: /* FMUL */
        !          1069:                        case 0x63: /* FSMUL */
        !          1070:                        case 0x67: /* FDMUL */
        !          1071:                        case 0x24: /* FSGLDIV */
        !          1072:                        case 0x27: /* FSGLMUL */
        !          1073:                        case 0x28: /* FSUB */
        !          1074:                        case 0x68: /* FSSUB */
        !          1075:                        case 0x6c: /* FDSUB */
        !          1076:                        case 0x38: /* FCMP */
        !          1077:                        case 0x3a: /* FTST */
        !          1078:                                return false;
1.1.1.4   root     1079:                        case 0x01: /* FINT */
                   1080:                        case 0x03: /* FINTRZ */
                   1081:                        // Unimplemented only in 68040.
1.1.1.6 ! root     1082:                        if(currprefs.cpu_model != 68040) {
        !          1083:                                return false;
1.1.1.4   root     1084:                        }
1.1.1.6 ! root     1085:                        default:
        !          1086:                        fp_unimp_instruction(opcode, extra, ea, oldpc, src, reg, -1);
        !          1087:                        return true;
        !          1088:                }
        !          1089:        }
        !          1090:        return false;
        !          1091: }
        !          1092: 
        !          1093: static bool fault_if_unimplemented_6888x (uae_u16 opcode, uae_u16 extra, uaecptr oldpc)
        !          1094: {
        !          1095:        if ((currprefs.fpu_model == 68881 || currprefs.fpu_model == 68882) && currprefs.fpu_no_unimplemented) {
        !          1096:                uae_u16 v = extra & 0x7f;
        !          1097:                switch(v)
        !          1098:                {
        !          1099:                        case 0x00: /* FMOVE */
        !          1100:                        case 0x01: /* FINT */
1.1.1.4   root     1101:                        case 0x02: /* FSINH */
1.1.1.6 ! root     1102:                        case 0x03: /* FINTRZ */
        !          1103:                        case 0x04: /* FSQRT */
1.1.1.4   root     1104:                        case 0x06: /* FLOGNP1 */
                   1105:                        case 0x08: /* FETOXM1 */
                   1106:                        case 0x09: /* FTANH */
                   1107:                        case 0x0a: /* FATAN */
                   1108:                        case 0x0c: /* FASIN */
                   1109:                        case 0x0d: /* FATANH */
                   1110:                        case 0x0e: /* FSIN */
                   1111:                        case 0x0f: /* FTAN */
                   1112:                        case 0x10: /* FETOX */
                   1113:                        case 0x11: /* FTWOTOX */
                   1114:                        case 0x12: /* FTENTOX */
                   1115:                        case 0x14: /* FLOGN */
                   1116:                        case 0x15: /* FLOG10 */
                   1117:                        case 0x16: /* FLOG2 */
1.1.1.6 ! root     1118:                        case 0x18: /* FABS */
1.1.1.4   root     1119:                        case 0x19: /* FCOSH */
1.1.1.6 ! root     1120:                        case 0x1a: /* FNEG */
1.1.1.4   root     1121:                        case 0x1c: /* FACOS */
                   1122:                        case 0x1d: /* FCOS */
                   1123:                        case 0x1e: /* FGETEXP */
                   1124:                        case 0x1f: /* FGETMAN */
1.1.1.6 ! root     1125:                        case 0x20: /* FDIV */
        !          1126:                        case 0x21: /* FMOD */
        !          1127:                        case 0x22: /* FADD */
        !          1128:                        case 0x23: /* FMUL */
        !          1129:                        case 0x24: /* FSGLDIV */
        !          1130:                        case 0x25: /* FREM */
        !          1131:                        case 0x26: /* FSCALE */
        !          1132:                        case 0x27: /* FSGLMUL */
        !          1133:                        case 0x28: /* FSUB */
1.1.1.4   root     1134:                        case 0x30: /* FSINCOS */
                   1135:                        case 0x31: /* FSINCOS */
                   1136:                        case 0x32: /* FSINCOS */
                   1137:                        case 0x33: /* FSINCOS */
                   1138:                        case 0x34: /* FSINCOS */
                   1139:                        case 0x35: /* FSINCOS */
                   1140:                        case 0x36: /* FSINCOS */
                   1141:                        case 0x37: /* FSINCOS */
1.1.1.6 ! root     1142:                        case 0x38: /* FCMP */
        !          1143:                        case 0x3a: /* FTST */
        !          1144:                                return false;
        !          1145:                        default:
        !          1146:                                fpu_noinst (opcode, oldpc);
        !          1147:                                return true;
1.1.1.4   root     1148:                }
                   1149:        }
                   1150:        return false;
                   1151: }
                   1152: 
1.1.1.6 ! root     1153: static bool fault_if_60 (void)
1.1.1.4   root     1154: {
                   1155:        if (currprefs.cpu_model == 68060 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
1.1.1.6 ! root     1156:                Exception(60);
1.1.1.4   root     1157:                return true;
                   1158:        }
                   1159:        return false;
                   1160: }
                   1161: 
                   1162: static bool fault_if_no_fpu_u (uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc)
                   1163: {
                   1164:        if (fault_if_no_fpu (opcode, extra, ea, oldpc))
                   1165:                return true;
                   1166:        if (currprefs.cpu_model == 68060 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
                   1167:                // 68060 FTRAP, FDBcc or FScc are not implemented.
1.1.1.6 ! root     1168:                regs.fp_unimp_ins = true;
        !          1169:                regs.fp_ea = ea;
        !          1170:                fp_unimp_instruction_exception_pending();
1.1.1.4   root     1171:                return true;
                   1172:        }
                   1173:        return false;
                   1174: }
                   1175: 
                   1176: static bool fault_if_no_6888x (uae_u16 opcode, uae_u16 extra, uaecptr oldpc)
                   1177: {
                   1178:        if (currprefs.cpu_model < 68040 && currprefs.fpu_model <= 0) {
                   1179: #if EXCEPTION_FPP
                   1180:                write_log (_T("6888x no FPU: %04X-%04X PC=%08X\n"), opcode, extra, oldpc);
                   1181: #endif
                   1182:                m68k_setpc (oldpc);
                   1183:                regs.fp_exception = true;
                   1184:                op_illg (opcode);
1.1.1.6 ! root     1185:                return true;
        !          1186:        }
        !          1187:        return false;
1.1.1.4   root     1188: }
                   1189: 
1.1.1.6 ! root     1190: static int get_fpu_version (int model)
1.1.1.4   root     1191: {
1.1.1.6 ! root     1192:        int v = 0;
1.1.1.4   root     1193: 
1.1.1.6 ! root     1194:        switch (model)
        !          1195:        {
        !          1196:        case 68881:
        !          1197:        case 68882:
        !          1198:                v = 0x1f;
        !          1199:                break;
        !          1200:        case 68040:
        !          1201:                if (currprefs.fpu_revision == 0x40)
        !          1202:                        v = 0x40;
        !          1203:                else
        !          1204:                        v = 0x41;
        !          1205:                break;
1.1.1.4   root     1206:        }
1.1.1.6 ! root     1207:        return v;
        !          1208: }
1.1.1.4   root     1209: 
1.1.1.6 ! root     1210: static void fpu_null (void)
        !          1211: {
        !          1212:        int i;
        !          1213:        regs.fpu_state = 0;
        !          1214:        regs.fpu_exp_state = 0;
        !          1215:        regs.fpcr = 0;
        !          1216:        regs.fpsr = 0;
        !          1217:        regs.fpiar = 0;
        !          1218:        for (i = 0; i < 8; i++)
        !          1219:                fpnan (&regs.fp[i]);
        !          1220: }
1.1.1.4   root     1221: 
1.1.1.6 ! root     1222: // 68040/060 does not support denormals
        !          1223: static bool normalize_or_fault_if_no_denormal_support(uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *src)
        !          1224: {
        !          1225:        if (!currprefs.fpu_softfloat)
        !          1226:                return false;
        !          1227:        if (fpp_is_unnormal(src) || fpp_is_denormal(src)) {
        !          1228:                if (currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
        !          1229:                        if (fpp_is_zero(src)) {
        !          1230:                                fpp_normalize(src); // 68040/060 can only fix unnormal zeros
1.1.1.4   root     1231:                        } else {
1.1.1.6 ! root     1232:                                fp_unimp_datatype(opcode, extra, ea, oldpc, src, NULL);
        !          1233:                                return true;
1.1.1.4   root     1234:                        }
1.1.1.6 ! root     1235:                } else {
        !          1236:                        fpp_normalize(src);
1.1.1.4   root     1237:                }
                   1238:        }
1.1.1.6 ! root     1239:        return false;
        !          1240: }
        !          1241: static bool normalize_or_fault_if_no_denormal_support_dst(uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *dst, fpdata *src)
        !          1242: {
        !          1243:        if (!currprefs.fpu_softfloat)
        !          1244:                return false;
        !          1245:        if (fpp_is_unnormal(dst) || fpp_is_denormal(dst)) {
        !          1246:                if (currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
        !          1247:                        if (fpp_is_zero(dst)) {
        !          1248:                                fpp_normalize(dst); // 68040/060 can only fix unnormal zeros
        !          1249:                        } else {
        !          1250:                                fp_unimp_datatype(opcode, extra, ea, oldpc, src, NULL);
        !          1251:                                return true;
        !          1252:                        }
        !          1253:                } else {
        !          1254:                        fpp_normalize(dst);
1.1.1.4   root     1255:                }
                   1256:        }
1.1.1.6 ! root     1257:        return false;
1.1.1.4   root     1258: }
                   1259: 
1.1.1.6 ! root     1260: // 68040/060 does not support packed decimal format
        !          1261: static bool fault_if_no_packed_support(uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *src, uae_u32 *packed)
1.1.1.4   root     1262: {
1.1.1.6 ! root     1263:        if (currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
        !          1264:                fp_unimp_datatype(opcode, extra, ea, oldpc, src, packed);
        !          1265:                return true;
1.1.1.4   root     1266:        }
                   1267:        return false;
1.1.1.6 ! root     1268:  }
        !          1269: 
        !          1270: // 68040 does not support move to integer format
        !          1271: static bool fault_if_68040_integer_nonmaskable(uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *src)
1.1.1.4   root     1272: {
1.1.1.6 ! root     1273:        if (currprefs.cpu_model == 68040 && currprefs.fpu_model && currprefs.fpu_softfloat) {
        !          1274:                fpsr_make_status();
        !          1275:                if (regs.fpsr & (FPSR_SNAN | FPSR_OPERR)) {
        !          1276:                        fpsr_check_arithmetic_exception(FPSR_SNAN | FPSR_OPERR, src, opcode, extra, ea);
        !          1277:                        fp_exception_pending(false); // post
1.1.1.4   root     1278:                        return true;
1.1       root     1279:                }
                   1280:        }
1.1.1.4   root     1281:        return false;
1.1       root     1282: }
                   1283: 
1.1.1.4   root     1284: static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr oldpc, uae_u32 *adp)
1.1       root     1285: {
                   1286:        int size, mode, reg;
                   1287:        uae_u32 ad = 0;
                   1288:        static const int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 };
                   1289:        static const int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
1.1.1.5   root     1290: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     1291:        uae_u32 exts[3];
1.1.1.5   root     1292: #else
                   1293:        uae_u32 exts[3] = { 0 };
                   1294: #endif
1.1.1.4   root     1295:        int doext = 0;
1.1       root     1296: 
                   1297:        if (!(extra & 0x4000)) {
1.1.1.4   root     1298:                if (fault_if_no_fpu (opcode, extra, 0, oldpc))
                   1299:                        return -1;
1.1       root     1300:                *src = regs.fp[(extra >> 10) & 7];
1.1.1.6 ! root     1301:                normalize_or_fault_if_no_denormal_support(opcode, extra, 0, oldpc, src);
1.1       root     1302:                return 1;
                   1303:        }
                   1304:        mode = (opcode >> 3) & 7;
                   1305:        reg = opcode & 7;
                   1306:        size = (extra >> 10) & 7;
                   1307: 
                   1308:        switch (mode) {
                   1309:                case 0:
1.1.1.6 ! root     1310:                        if ((size == 0 || size == 1 ||size == 4 || size == 6) && fault_if_no_fpu (opcode, extra, 0, oldpc))
        !          1311:                                return -1;
1.1.1.4   root     1312:                        switch (size)
                   1313:                        {
                   1314:                                case 6:
                   1315:                                        fpset(src, (uae_s8) m68k_dreg (regs, reg));
                   1316:                                        break;
                   1317:                                case 4:
                   1318:                                        fpset(src, (uae_s16) m68k_dreg (regs, reg));
                   1319:                                        break;
                   1320:                                case 0:
                   1321:                                        fpset(src, (uae_s32) m68k_dreg (regs, reg));
                   1322:                                        break;
                   1323:                                case 1:
1.1.1.6 ! root     1324:                                        fpp_to_single (src, m68k_dreg (regs, reg));
        !          1325:                                        normalize_or_fault_if_no_denormal_support(opcode, extra, 0, oldpc, src);
1.1.1.4   root     1326:                                        break;
                   1327:                                default:
                   1328:                                        return 0;
1.1       root     1329:                        }
                   1330:                        return 1;
                   1331:                case 1:
                   1332:                        return 0;
                   1333:                case 2:
                   1334:                        ad = m68k_areg (regs, reg);
                   1335:                        break;
                   1336:                case 3:
1.1.1.6 ! root     1337:                        // Also needed by fault_if_no_fpu 
        !          1338:                        mmufixup[0].reg = reg;
        !          1339:                        mmufixup[0].value = m68k_areg (regs, reg);
        !          1340:                        fpu_mmu_fixup = true;
1.1       root     1341:                        ad = m68k_areg (regs, reg);
                   1342:                        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
                   1343:                        break;
                   1344:                case 4:
1.1.1.6 ! root     1345:                        // Also needed by fault_if_no_fpu 
        !          1346:                        mmufixup[0].reg = reg;
        !          1347:                        mmufixup[0].value = m68k_areg (regs, reg);
        !          1348:                        fpu_mmu_fixup = true;
1.1       root     1349:                        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
                   1350:                        ad = m68k_areg (regs, reg);
1.1.1.6 ! root     1351:                        // 68060 no fpu -(an): EA points to -4, not -12 if extended precision
        !          1352:                        if (currprefs.cpu_model == 68060 && if_no_fpu() && sz1[size] == 12)
        !          1353:                                ad += 8;
1.1       root     1354:                        break;
                   1355:                case 5:
1.1.1.4   root     1356:                        ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_cp_next_iword ();
1.1       root     1357:                        break;
                   1358:                case 6:
1.1.1.4   root     1359:                        ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg), 0);
1.1       root     1360:                        break;
                   1361:                case 7:
1.1.1.4   root     1362:                        switch (reg)
                   1363:                        {
                   1364:                                case 0: // (xxx).W
                   1365:                                        ad = (uae_s32) (uae_s16) x_cp_next_iword ();
                   1366:                                        break;
                   1367:                                case 1: // (xxx).L
                   1368:                                        ad = x_cp_next_ilong ();
                   1369:                                        break;
                   1370:                                case 2: // (d16,PC)
                   1371:                                        ad = m68k_getpc ();
                   1372:                                        ad += (uae_s32) (uae_s16) x_cp_next_iword ();
                   1373:                                        break;
                   1374:                                case 3: // (d8,PC,Xn)+
                   1375:                                        ad = x_cp_get_disp_ea_020 (m68k_getpc (), 0);
                   1376:                                        break;
                   1377:                                case 4: // #imm
                   1378:                                        doext = 1;
                   1379:                                        switch (size)
                   1380:                                        {
                   1381:                                                case 0: // L
                   1382:                                                case 1: // S
                   1383:                                                exts[0] = x_cp_next_ilong ();
                   1384:                                                break;
                   1385:                                                case 2: // X
                   1386:                                                case 3: // P
                   1387:                                                // 68060 and immediate X or P: unimplemented effective address
1.1.1.6 ! root     1388:                                                if (fault_if_60())
1.1.1.4   root     1389:                                                        return -1;
                   1390:                                                exts[0] = x_cp_next_ilong ();
                   1391:                                                exts[1] = x_cp_next_ilong ();
                   1392:                                                exts[2] = x_cp_next_ilong ();
                   1393:                                                break;
                   1394:                                                case 4: // W
                   1395:                                                exts[0] = x_cp_next_iword ();
                   1396:                                                break;
                   1397:                                                case 5: // D
                   1398:                                                exts[0] = x_cp_next_ilong ();
                   1399:                                                exts[1] = x_cp_next_ilong ();
                   1400:                                                break;
                   1401:                                                case 6: // B
                   1402:                                                exts[0] = x_cp_next_iword ();
                   1403:                                                break;
                   1404:                                        }
                   1405:                                        break;
                   1406:                                default:
                   1407:                                        return 0;
                   1408:                        }
                   1409:        }
                   1410: 
                   1411: 
1.1.1.6 ! root     1412:        if (fault_if_no_fpu (opcode, extra, ad, oldpc))
1.1.1.4   root     1413:                return -1;
                   1414: 
1.1.1.6 ! root     1415:        *adp = ad;
        !          1416:        uae_u32 adold = ad;
        !          1417: 
        !          1418:        if (currprefs.fpu_model == 68060) {
        !          1419:                // Skip if 68040 because FSAVE frame can store both src and dst
        !          1420:                if (fault_if_unimplemented_680x0(opcode, extra, ad, oldpc, src, -1)) {
        !          1421:                        return -1;
        !          1422:                }
        !          1423:        }
        !          1424: 
1.1.1.4   root     1425:        switch (size)
                   1426:        {
1.1       root     1427:                case 0:
1.1.1.4   root     1428:                        fpset(src, (uae_s32) (doext ? exts[0] : x_cp_get_long (ad)));
1.1       root     1429:                        break;
                   1430:                case 1:
1.1.1.6 ! root     1431:                        fpp_to_single (src, (doext ? exts[0] : x_cp_get_long (ad)));
        !          1432:                        normalize_or_fault_if_no_denormal_support(opcode, extra, adold, oldpc, src);
1.1       root     1433:                        break;
                   1434:                case 2:
1.1.1.4   root     1435:                        {
                   1436:                                uae_u32 wrd1, wrd2, wrd3;
                   1437:                                wrd1 = (doext ? exts[0] : x_cp_get_long (ad));
                   1438:                                ad += 4;
                   1439:                                wrd2 = (doext ? exts[1] : x_cp_get_long (ad));
                   1440:                                ad += 4;
                   1441:                                wrd3 = (doext ? exts[2] : x_cp_get_long (ad));
1.1.1.6 ! root     1442:                                fpp_to_exten (src, wrd1, wrd2, wrd3);
        !          1443:                                normalize_or_fault_if_no_denormal_support(opcode, extra, adold, oldpc, src);
1.1.1.4   root     1444:                        }
1.1       root     1445:                        break;
                   1446:                case 3:
1.1.1.4   root     1447:                        {
                   1448:                                uae_u32 wrd[3];
                   1449:                                if (currprefs.cpu_model == 68060) {
1.1.1.6 ! root     1450:                                        if (fault_if_no_packed_support (opcode, extra, adold, oldpc, NULL, wrd))
        !          1451:                                                return 1;
1.1.1.4   root     1452:                                }
                   1453:                                wrd[0] = (doext ? exts[0] : x_cp_get_long (ad));
                   1454:                                ad += 4;
                   1455:                                wrd[1] = (doext ? exts[1] : x_cp_get_long (ad));
                   1456:                                ad += 4;
                   1457:                                wrd[2] = (doext ? exts[2] : x_cp_get_long (ad));
1.1.1.6 ! root     1458:                                if (fault_if_no_packed_support (opcode, extra, adold, oldpc, NULL, wrd))
        !          1459:                                        return 1;
        !          1460:                                fpp_to_pack (src, wrd, 0);
        !          1461:                                fpp_normalize(src);
1.1.1.4   root     1462:                                return 1;
                   1463:                        }
1.1       root     1464:                        break;
                   1465:                case 4:
1.1.1.4   root     1466:                        fpset(src, (uae_s16) (doext ? exts[0] : x_cp_get_word (ad)));
1.1       root     1467:                        break;
1.1.1.4   root     1468:                case 5:
                   1469:                        {
                   1470:                                uae_u32 wrd1, wrd2;
                   1471:                                wrd1 = (doext ? exts[0] : x_cp_get_long (ad));
                   1472:                                ad += 4;
                   1473:                                wrd2 = (doext ? exts[1] : x_cp_get_long (ad));
1.1.1.6 ! root     1474:                                fpp_to_double (src, wrd1, wrd2);
        !          1475:                                normalize_or_fault_if_no_denormal_support(opcode, extra, adold, oldpc, src);
1.1       root     1476:                        }
                   1477:                        break;
1.1.1.4   root     1478:                case 6:
                   1479:                        fpset(src, (uae_s8) (doext ? exts[0] : x_cp_get_byte (ad)));
1.1       root     1480:                        break;
                   1481:                default:
                   1482:                        return 0;
                   1483:        }
                   1484:        return 1;
                   1485: }
                   1486: 
1.1.1.6 ! root     1487: static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr oldpc, uae_u32 *adp)
1.1       root     1488: {
                   1489:        int size, mode, reg;
1.1.1.4   root     1490:        uae_u32 ad = 0;
1.1.1.6 ! root     1491:        static const int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 };
        !          1492:        static const int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
1.1       root     1493: 
                   1494: #if DEBUG_FPP
                   1495:        if (!isinrom ())
1.1.1.6 ! root     1496:                write_log (_T("PUTFP: %04X %04X\n"), opcode, extra);
1.1       root     1497: #endif
1.1.1.6 ! root     1498: #if 0
1.1       root     1499:        if (!(extra & 0x4000)) {
1.1.1.4   root     1500:                if (fault_if_no_fpu (opcode, extra, 0, oldpc))
                   1501:                        return 1;
                   1502:                regs.fp[(extra >> 10) & 7] = *value;
1.1       root     1503:                return 1;
                   1504:        }
1.1.1.6 ! root     1505: #endif
1.1       root     1506:        reg = opcode & 7;
                   1507:        mode = (opcode >> 3) & 7;
                   1508:        size = (extra >> 10) & 7;
1.1.1.4   root     1509:        switch (mode)
                   1510:        {
1.1       root     1511:                case 0:
1.1.1.6 ! root     1512: 
        !          1513:                        if ((size == 0 || size == 1 ||size == 4 || size == 6) && fault_if_no_fpu (opcode, extra, 0, oldpc))
        !          1514:                                return -1;
1.1.1.4   root     1515:                        switch (size)
                   1516:                        {
                   1517:                                case 6:
1.1.1.6 ! root     1518:                                        if (normalize_or_fault_if_no_denormal_support(opcode, extra, 0, oldpc, value))
        !          1519:                                                return 1;
        !          1520:                                        m68k_dreg (regs, reg) = (uae_u32)(((fpp_to_int (value, 0) & 0xff)
1.1.1.4   root     1521:                                                | (m68k_dreg (regs, reg) & ~0xff)));
1.1.1.6 ! root     1522:                                        if (fault_if_68040_integer_nonmaskable(opcode, extra, ad, oldpc, value))
        !          1523:                                                return -1;
1.1.1.4   root     1524:                                        break;
                   1525:                                case 4:
1.1.1.6 ! root     1526:                                        if (normalize_or_fault_if_no_denormal_support(opcode, extra, 0, oldpc, value))
        !          1527:                                                return 1;
        !          1528:                                        m68k_dreg (regs, reg) = (uae_u32)(((fpp_to_int (value, 1) & 0xffff)
1.1.1.4   root     1529:                                                | (m68k_dreg (regs, reg) & ~0xffff)));
1.1.1.6 ! root     1530:                                        if (fault_if_68040_integer_nonmaskable(opcode, extra, ad, oldpc, value))
        !          1531:                                                return -1;
1.1.1.4   root     1532:                                        break;
                   1533:                                case 0:
1.1.1.6 ! root     1534:                                        if (normalize_or_fault_if_no_denormal_support(opcode, extra, 0, oldpc, value))
        !          1535:                                                return 1;
        !          1536:                                        m68k_dreg (regs, reg) = (uae_u32)fpp_to_int (value, 2);
        !          1537:                                        if (fault_if_68040_integer_nonmaskable(opcode, extra, ad, oldpc, value))
        !          1538:                                                return -1;
1.1.1.4   root     1539:                                        break;
                   1540:                                case 1:
1.1.1.6 ! root     1541:                                        if (normalize_or_fault_if_no_denormal_support(opcode, extra, 0, oldpc, value))
        !          1542:                                                return 1;
        !          1543:                                        m68k_dreg (regs, reg) = fpp_from_single (value);
1.1.1.4   root     1544:                                        break;
                   1545:                                default:
                   1546:                                        return 0;
1.1       root     1547:                        }
                   1548:                        return 1;
                   1549:                case 1:
                   1550:                        return 0;
                   1551:                case 2:
                   1552:                        ad = m68k_areg (regs, reg);
                   1553:                        break;
                   1554:                case 3:
1.1.1.6 ! root     1555:                        // Also needed by fault_if_no_fpu 
        !          1556:                        mmufixup[0].reg = reg;
        !          1557:                        mmufixup[0].value = m68k_areg (regs, reg);
        !          1558:                        fpu_mmu_fixup = true;
1.1       root     1559:                        ad = m68k_areg (regs, reg);
                   1560:                        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
                   1561:                        break;
                   1562:                case 4:
1.1.1.6 ! root     1563:                        // Also needed by fault_if_no_fpu 
        !          1564:                        mmufixup[0].reg = reg;
        !          1565:                        mmufixup[0].value = m68k_areg (regs, reg);
        !          1566:                        fpu_mmu_fixup = true;
1.1       root     1567:                        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
                   1568:                        ad = m68k_areg (regs, reg);
1.1.1.6 ! root     1569:                        // 68060 no fpu -(an): EA points to -4, not -12 if extended precision
        !          1570:                        if (currprefs.cpu_model == 68060 && if_no_fpu() && sz1[size] == 12)
        !          1571:                                ad += 8;
1.1       root     1572:                        break;
                   1573:                case 5:
1.1.1.4   root     1574:                        ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_cp_next_iword ();
1.1       root     1575:                        break;
                   1576:                case 6:
1.1.1.4   root     1577:                        ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg), 0);
1.1       root     1578:                        break;
                   1579:                case 7:
1.1.1.4   root     1580:                        switch (reg)
                   1581:                        {
                   1582:                                case 0:
                   1583:                                        ad = (uae_s32) (uae_s16) x_cp_next_iword ();
                   1584:                                        break;
                   1585:                                case 1:
                   1586:                                        ad = x_cp_next_ilong ();
                   1587:                                        break;
                   1588:                                case 2:
                   1589:                                        ad = m68k_getpc ();
                   1590:                                        ad += (uae_s32) (uae_s16) x_cp_next_iword ();
                   1591:                                        break;
                   1592:                                case 3:
                   1593:                                        ad = x_cp_get_disp_ea_020 (m68k_getpc (), 0);
                   1594:                                        break;
                   1595:                                default:
                   1596:                                        return 0;
1.1       root     1597:                        }
                   1598:        }
1.1.1.4   root     1599: 
1.1.1.6 ! root     1600:        *adp = ad;
        !          1601: 
1.1.1.4   root     1602:        if (fault_if_no_fpu (opcode, extra, ad, oldpc))
1.1.1.6 ! root     1603:                return -1;
1.1.1.4   root     1604: 
                   1605:        switch (size)
                   1606:        {
1.1       root     1607:                case 0:
1.1.1.6 ! root     1608:                        if (normalize_or_fault_if_no_denormal_support(opcode, extra, ad, oldpc, value))
1.1.1.4   root     1609:                                return 1;
1.1.1.6 ! root     1610:                        x_cp_put_long(ad, (uae_u32)fpp_to_int(value, 2));
        !          1611:                        if (fault_if_68040_integer_nonmaskable(opcode, extra, ad, oldpc, value))
        !          1612:                                return -1;
1.1       root     1613:                        break;
                   1614:                case 1:
1.1.1.6 ! root     1615:                        if (normalize_or_fault_if_no_denormal_support(opcode, extra, ad, oldpc, value))
        !          1616:                                return 1;
        !          1617:                        x_cp_put_long(ad, fpp_from_single(value));
1.1       root     1618:                        break;
                   1619:                case 2:
                   1620:                        {
1.1.1.6 ! root     1621:                                if (normalize_or_fault_if_no_denormal_support(opcode, extra, ad, oldpc, value))
1.1.1.4   root     1622:                                        return 1;
1.1.1.6 ! root     1623:                                uae_u32 wrd1, wrd2, wrd3;
        !          1624:                                fpp_from_exten(value, &wrd1, &wrd2, &wrd3);
1.1.1.4   root     1625:                                x_cp_put_long (ad, wrd1);
1.1       root     1626:                                ad += 4;
1.1.1.4   root     1627:                                x_cp_put_long (ad, wrd2);
1.1       root     1628:                                ad += 4;
1.1.1.4   root     1629:                                x_cp_put_long (ad, wrd3);
1.1       root     1630:                        }
                   1631:                        break;
1.1.1.4   root     1632:                case 3: // Packed-Decimal Real with Static k-Factor
                   1633:                case 7: // Packed-Decimal Real with Dynamic k-Factor (P{Dn}) (reg to memory only)
1.1       root     1634:                        {
1.1.1.4   root     1635:                                uae_u32 wrd[3];
                   1636:                                int kfactor;
1.1.1.6 ! root     1637:                                if (fault_if_no_packed_support (opcode, extra, ad, oldpc, value, wrd))
1.1.1.4   root     1638:                                        return 1;
                   1639:                                kfactor = size == 7 ? m68k_dreg (regs, (extra >> 4) & 7) : extra;
                   1640:                                kfactor &= 127;
                   1641:                                if (kfactor & 64)
                   1642:                                        kfactor |= ~63;
1.1.1.6 ! root     1643:                                fpp_normalize(value);
        !          1644:                                fpp_from_pack(value, wrd, kfactor);
1.1.1.4   root     1645:                                x_cp_put_long (ad, wrd[0]);
1.1       root     1646:                                ad += 4;
1.1.1.4   root     1647:                                x_cp_put_long (ad, wrd[1]);
1.1       root     1648:                                ad += 4;
1.1.1.4   root     1649:                                x_cp_put_long (ad, wrd[2]);
1.1       root     1650:                        }
                   1651:                        break;
                   1652:                case 4:
1.1.1.6 ! root     1653:                        if (normalize_or_fault_if_no_denormal_support(opcode, extra, ad, oldpc, value))
1.1.1.4   root     1654:                                return 1;
1.1.1.6 ! root     1655:                        x_cp_put_word(ad, (uae_s16)fpp_to_int(value, 1));
        !          1656:                        if (fault_if_68040_integer_nonmaskable(opcode, extra, ad, oldpc, value))
        !          1657:                                return -1;
1.1.1.4   root     1658:                        break;
                   1659:                case 5:
                   1660:                        {
1.1.1.6 ! root     1661:                                if (normalize_or_fault_if_no_denormal_support(opcode, extra, ad, oldpc, value))
        !          1662:                                        return 1;
1.1.1.4   root     1663:                                uae_u32 wrd1, wrd2;
1.1.1.6 ! root     1664:                                fpp_from_double(value, &wrd1, &wrd2);
1.1.1.4   root     1665:                                x_cp_put_long (ad, wrd1);
                   1666:                                ad += 4;
                   1667:                                x_cp_put_long (ad, wrd2);
                   1668:                        }
1.1       root     1669:                        break;
                   1670:                case 6:
1.1.1.6 ! root     1671:                        if (normalize_or_fault_if_no_denormal_support(opcode, extra, ad, oldpc, value))
1.1.1.4   root     1672:                                return 1;
1.1.1.6 ! root     1673:                        x_cp_put_byte(ad, (uae_s8)fpp_to_int(value, 0));
        !          1674:                        if (fault_if_68040_integer_nonmaskable(opcode, extra, ad, oldpc, value))
        !          1675:                                return -1;
1.1       root     1676:                        break;
                   1677:                default:
                   1678:                        return 0;
                   1679:        }
                   1680:        return 1;
                   1681: }
                   1682: 
1.1.1.6 ! root     1683: static int get_fp_ad (uae_u32 opcode, uae_u32 * ad)
1.1       root     1684: {
                   1685:        int mode;
                   1686:        int reg;
                   1687: 
                   1688:        mode = (opcode >> 3) & 7;
                   1689:        reg = opcode & 7;
1.1.1.4   root     1690:        switch (mode)
                   1691:        {
1.1       root     1692:                case 0:
                   1693:                case 1:
                   1694:                        return 0;
                   1695:                case 2:
                   1696:                        *ad = m68k_areg (regs, reg);
                   1697:                        break;
                   1698:                case 3:
                   1699:                        *ad = m68k_areg (regs, reg);
                   1700:                        break;
                   1701:                case 4:
                   1702:                        *ad = m68k_areg (regs, reg);
                   1703:                        break;
                   1704:                case 5:
1.1.1.4   root     1705:                        *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_cp_next_iword ();
1.1       root     1706:                        break;
                   1707:                case 6:
1.1.1.4   root     1708:                        *ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg), 0);
1.1       root     1709:                        break;
                   1710:                case 7:
1.1.1.4   root     1711:                        switch (reg)
                   1712:                        {
                   1713:                                case 0:
                   1714:                                        *ad = (uae_s32) (uae_s16) x_cp_next_iword ();
                   1715:                                        break;
                   1716:                                case 1:
                   1717:                                        *ad = x_cp_next_ilong ();
                   1718:                                        break;
                   1719:                                case 2:
                   1720:                                        *ad = m68k_getpc ();
                   1721:                                        *ad += (uae_s32) (uae_s16) x_cp_next_iword ();
                   1722:                                        break;
                   1723:                                case 3:
                   1724:                                        *ad = x_cp_get_disp_ea_020 (m68k_getpc (), 0);
                   1725:                                        break;
                   1726:                                default:
                   1727:                                        return 0;
1.1       root     1728:                        }
                   1729:        }
                   1730:        return 1;
                   1731: }
                   1732: 
1.1.1.4   root     1733: int fpp_cond (int condition)
1.1       root     1734: {
1.1.1.6 ! root     1735:        int NotANumber, N, Z;
1.1       root     1736: 
1.1.1.6 ! root     1737: #ifdef JIT
        !          1738:        if (currprefs.cachesize && currprefs.compfpu) {
        !          1739:                // JIT reads and writes regs.fpu_result
        !          1740:                NotANumber = fpp_is_nan(&regs.fp_result);
        !          1741:                N = fpp_is_neg(&regs.fp_result);
        !          1742:                Z = fpp_is_zero(&regs.fp_result);
        !          1743:        } else
        !          1744: #endif
        !          1745:        {
        !          1746:                NotANumber = (regs.fpsr & FPSR_CC_NAN) != 0;
        !          1747:                N = (regs.fpsr & FPSR_CC_N) != 0;
        !          1748:                Z = (regs.fpsr & FPSR_CC_Z) != 0;
        !          1749:        }
1.1       root     1750: 
1.1.1.6 ! root     1751:        if ((condition & 0x10) && NotANumber) {
        !          1752:                if (fpsr_set_bsun())
        !          1753:                        return -2;
        !          1754:        }
1.1       root     1755: 
1.1.1.4   root     1756:        switch (condition)
                   1757:        {
1.1       root     1758:                case 0x00:
                   1759:                        return 0;
                   1760:                case 0x01:
                   1761:                        return Z;
                   1762:                case 0x02:
                   1763:                        return !(NotANumber || Z || N);
                   1764:                case 0x03:
                   1765:                        return Z || !(NotANumber || N);
                   1766:                case 0x04:
                   1767:                        return N && !(NotANumber || Z);
                   1768:                case 0x05:
                   1769:                        return Z || (N && !NotANumber);
                   1770:                case 0x06:
                   1771:                        return !(NotANumber || Z);
                   1772:                case 0x07:
                   1773:                        return !NotANumber;
                   1774:                case 0x08:
                   1775:                        return NotANumber;
                   1776:                case 0x09:
                   1777:                        return NotANumber || Z;
                   1778:                case 0x0a:
                   1779:                        return NotANumber || !(N || Z);
                   1780:                case 0x0b:
                   1781:                        return NotANumber || Z || !N;
                   1782:                case 0x0c:
                   1783:                        return NotANumber || (N && !Z);
                   1784:                case 0x0d:
                   1785:                        return NotANumber || Z || N;
                   1786:                case 0x0e:
                   1787:                        return !Z;
                   1788:                case 0x0f:
                   1789:                        return 1;
                   1790:                case 0x10:
                   1791:                        return 0;
                   1792:                case 0x11:
                   1793:                        return Z;
                   1794:                case 0x12:
                   1795:                        return !(NotANumber || Z || N);
                   1796:                case 0x13:
                   1797:                        return Z || !(NotANumber || N);
                   1798:                case 0x14:
                   1799:                        return N && !(NotANumber || Z);
                   1800:                case 0x15:
                   1801:                        return Z || (N && !NotANumber);
                   1802:                case 0x16:
                   1803:                        return !(NotANumber || Z);
                   1804:                case 0x17:
                   1805:                        return !NotANumber;
                   1806:                case 0x18:
                   1807:                        return NotANumber;
                   1808:                case 0x19:
                   1809:                        return NotANumber || Z;
                   1810:                case 0x1a:
                   1811:                        return NotANumber || !(N || Z);
                   1812:                case 0x1b:
                   1813:                        return NotANumber || Z || !N;
                   1814:                case 0x1c:
                   1815:                        return NotANumber || (N && !Z);
                   1816:                case 0x1d:
                   1817:                        return NotANumber || Z || N;
                   1818:                case 0x1e:
                   1819:                        return !Z;
                   1820:                case 0x1f:
                   1821:                        return 1;
                   1822:        }
                   1823:        return -1;
                   1824: }
                   1825: 
1.1.1.4   root     1826: static void maybe_idle_state (void)
                   1827: {
                   1828:        // conditional floating point instruction does not change state
                   1829:        // from null to idle on 68040/060.
                   1830:        if (currprefs.fpu_model == 68881 || currprefs.fpu_model == 68882)
                   1831:                regs.fpu_state = 1;
                   1832: }
                   1833: 
1.1       root     1834: void fpuop_dbcc (uae_u32 opcode, uae_u16 extra)
                   1835: {
1.1.1.4   root     1836:        uaecptr pc = m68k_getpc ();
1.1       root     1837:        uae_s32 disp;
                   1838:        int cc;
                   1839: 
1.1.1.6 ! root     1840:        if (fp_exception_pending(true))
        !          1841:                return;
        !          1842: 
1.1.1.4   root     1843:        regs.fp_exception = false;
1.1       root     1844: #if DEBUG_FPP
                   1845:        if (!isinrom ())
1.1.1.4   root     1846:                write_log (_T("fdbcc_opp at %08x\n"), m68k_getpc ());
1.1       root     1847: #endif
1.1.1.4   root     1848:        if (fault_if_no_6888x (opcode, extra, pc - 4))
1.1       root     1849:                return;
                   1850: 
1.1.1.4   root     1851:        disp = (uae_s32) (uae_s16) x_cp_next_iword ();
                   1852:        if (fault_if_no_fpu_u (opcode, extra, pc + disp, pc - 4))
                   1853:                return;
                   1854:        regs.fpiar = pc - 4;
                   1855:        maybe_idle_state ();
1.1       root     1856:        cc = fpp_cond (extra & 0x3f);
1.1.1.4   root     1857:        if (cc < 0) {
1.1.1.6 ! root     1858:                if (cc == -2)
        !          1859:                        return; // BSUN
        !          1860:                fpu_op_illg (opcode, 0, regs.fpiar);
1.1       root     1861:        } else if (!cc) {
                   1862:                int reg = opcode & 0x7;
                   1863: 
                   1864:                m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & 0xffff0000)
                   1865:                        | (((m68k_dreg (regs, reg) & 0xffff) - 1) & 0xffff));
1.1.1.4   root     1866:                if ((m68k_dreg (regs, reg) & 0xffff) != 0xffff) {
1.1       root     1867:                        m68k_setpc (pc + disp);
1.1.1.4   root     1868:                        regs.fp_branch = true;
                   1869:                }
1.1       root     1870:        }
                   1871: }
                   1872: 
                   1873: void fpuop_scc (uae_u32 opcode, uae_u16 extra)
                   1874: {
1.1.1.3   root     1875:        uae_u32 ad = 0;
1.1       root     1876:        int cc;
1.1.1.4   root     1877:        uaecptr pc = m68k_getpc () - 4;
1.1       root     1878: 
1.1.1.6 ! root     1879:        if (fp_exception_pending(true))
        !          1880:                return;
        !          1881: 
1.1.1.4   root     1882:        regs.fp_exception = false;
1.1       root     1883: #if DEBUG_FPP
                   1884:        if (!isinrom ())
1.1.1.4   root     1885:                write_log (_T("fscc_opp at %08x\n"), m68k_getpc ());
1.1       root     1886: #endif
1.1.1.4   root     1887: 
                   1888:        if (fault_if_no_6888x (opcode, extra, pc))
                   1889:                return;
                   1890: 
                   1891:        if (opcode & 0x38) {
                   1892:                if (get_fp_ad (opcode, &ad) == 0) {
                   1893:                        fpu_noinst (opcode, regs.fpiar);
                   1894:                        return;
                   1895:                }
                   1896:        }
                   1897: 
                   1898:        if (fault_if_no_fpu_u (opcode, extra, ad, pc))
1.1       root     1899:                return;
                   1900: 
1.1.1.4   root     1901:        regs.fpiar = pc;
                   1902:        maybe_idle_state ();
1.1       root     1903:        cc = fpp_cond (extra & 0x3f);
1.1.1.4   root     1904:        if (cc < 0) {
1.1.1.6 ! root     1905:                if (cc == -2)
        !          1906:                        return; // BSUN
        !          1907:                fpu_op_illg (opcode, 0, regs.fpiar);
1.1       root     1908:        } else if ((opcode & 0x38) == 0) {
                   1909:                m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | (cc ? 0xff : 0x00);
                   1910:        } else {
1.1.1.4   root     1911:                x_cp_put_byte (ad, cc ? 0xff : 0x00);
1.1       root     1912:        }
                   1913: }
                   1914: 
                   1915: void fpuop_trapcc (uae_u32 opcode, uaecptr oldpc, uae_u16 extra)
                   1916: {
                   1917:        int cc;
                   1918: 
1.1.1.6 ! root     1919:        if (fp_exception_pending(true))
        !          1920:                return;
        !          1921: 
1.1.1.4   root     1922:        regs.fp_exception = false;
1.1       root     1923: #if DEBUG_FPP
                   1924:        if (!isinrom ())
1.1.1.4   root     1925:                write_log (_T("ftrapcc_opp at %08x\n"), m68k_getpc ());
1.1       root     1926: #endif
1.1.1.4   root     1927:        if (fault_if_no_fpu_u (opcode, extra, 0, oldpc))
1.1       root     1928:                return;
                   1929: 
1.1.1.4   root     1930:        regs.fpiar = oldpc;
                   1931:        maybe_idle_state ();
1.1       root     1932:        cc = fpp_cond (extra & 0x3f);
1.1.1.4   root     1933:        if (cc < 0) {
1.1.1.6 ! root     1934:                if (cc == -2)
        !          1935:                        return; // BSUN
        !          1936:                fpu_op_illg (opcode, 0, regs.fpiar);
1.1.1.4   root     1937:        } else if (cc) {
                   1938:                Exception (7);
1.1       root     1939:        }
                   1940: }
                   1941: 
1.1.1.4   root     1942: void fpuop_bcc (uae_u32 opcode, uaecptr oldpc, uae_u32 extra)
1.1       root     1943: {
                   1944:        int cc;
                   1945: 
1.1.1.6 ! root     1946:        if (fp_exception_pending(true))
        !          1947:                return;
        !          1948: 
1.1.1.4   root     1949:        regs.fp_exception = false;
1.1       root     1950: #if DEBUG_FPP
                   1951:        if (!isinrom ())
1.1.1.4   root     1952:                write_log (_T("fbcc_opp at %08x\n"), m68k_getpc ());
1.1       root     1953: #endif
1.1.1.4   root     1954:        if (fault_if_no_fpu (opcode, extra, 0, oldpc - 2))
1.1       root     1955:                return;
                   1956: 
1.1.1.4   root     1957:        regs.fpiar = oldpc - 2;
                   1958:        maybe_idle_state ();
1.1       root     1959:        cc = fpp_cond (opcode & 0x3f);
1.1.1.4   root     1960:        if (cc < 0) {
1.1.1.6 ! root     1961:                if (cc == -2)
        !          1962:                        return; // BSUN
        !          1963:                fpu_op_illg (opcode, 0, regs.fpiar);
1.1       root     1964:        } else if (cc) {
                   1965:                if ((opcode & 0x40) == 0)
                   1966:                        extra = (uae_s32) (uae_s16) extra;
1.1.1.4   root     1967:                m68k_setpc (oldpc + extra);
                   1968:                regs.fp_branch = true;
1.1       root     1969:        }
                   1970: }
                   1971: 
                   1972: void fpuop_save (uae_u32 opcode)
                   1973: {
1.1.1.6 ! root     1974:        uae_u32 ad, adp;
1.1       root     1975:        int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
1.1.1.6 ! root     1976:        int fpu_version = get_fpu_version (currprefs.fpu_model);
1.1.1.4   root     1977:        uaecptr pc = m68k_getpc () - 2;
1.1       root     1978:        int i;
                   1979: 
1.1.1.4   root     1980:        regs.fp_exception = false;
1.1       root     1981: #if DEBUG_FPP
                   1982:        if (!isinrom ())
1.1.1.4   root     1983:                write_log (_T("fsave_opp at %08x\n"), m68k_getpc ());
1.1       root     1984: #endif
1.1.1.4   root     1985: 
                   1986:        if (fault_if_no_6888x (opcode, 0, pc))
1.1       root     1987:                return;
                   1988: 
                   1989:        if (get_fp_ad (opcode, &ad) == 0) {
1.1.1.4   root     1990:                fpu_op_illg (opcode, 0, pc);
1.1       root     1991:                return;
                   1992:        }
                   1993: 
1.1.1.4   root     1994:        if (fault_if_no_fpu (opcode, 0, ad, pc))
                   1995:                return;
                   1996: 
1.1.1.6 ! root     1997: //     write_log(_T("FSAVE %08x %08x\n"), M68K_GETPC, ad);
        !          1998: 
1.1       root     1999:        if (currprefs.fpu_model == 68060) {
1.1.1.6 ! root     2000: 
1.1.1.4   root     2001:                /* 12 byte 68060 NULL/IDLE/EXCP frame.  */
                   2002:                int frame_size = 12;
1.1.1.6 ! root     2003:                uae_u32 frame_id;
1.1.1.4   root     2004:                
                   2005:                if (regs.fpu_exp_state > 1) {
1.1.1.6 ! root     2006:                        frame_id = 0x0000e000 | fsave_data.v;
1.1.1.4   root     2007: 
1.1.1.6 ! root     2008: #if 0
        !          2009:                        write_log(_T("68060 FSAVE EXCP %s\n"), fpp_print(&fsave_data.src));
1.1.1.4   root     2010: #endif
                   2011: 
1.1       root     2012:                } else {
1.1.1.4   root     2013:                        frame_id = regs.fpu_state == 0 ? 0x00000000 : 0x00006000;
1.1       root     2014:                }
1.1.1.4   root     2015:                if (incr < 0)
                   2016:                        ad -= frame_size;
1.1.1.6 ! root     2017:                adp = ad;
        !          2018:                x_put_long (ad, (fsave_data.eo[0] & 0xffff0000) | frame_id);
1.1.1.4   root     2019:                ad += 4;
1.1.1.6 ! root     2020:                x_put_long (ad, fsave_data.eo[1]);
1.1.1.4   root     2021:                ad += 4;
1.1.1.6 ! root     2022:                x_put_long (ad, fsave_data.eo[2]);
1.1.1.4   root     2023:                ad += 4;
1.1.1.6 ! root     2024: 
1.1       root     2025:        } else if (currprefs.fpu_model == 68040) {
1.1.1.6 ! root     2026: 
1.1.1.4   root     2027:                if (!regs.fpu_exp_state) {
                   2028:                        /* 4 byte 68040 NULL/IDLE frame.  */
                   2029:                        uae_u32 frame_id = regs.fpu_state == 0 ? 0 : fpu_version << 24;
1.1.1.6 ! root     2030:                        if (incr < 0)
1.1.1.4   root     2031:                                ad -= 4;
1.1.1.6 ! root     2032:                        adp = ad;
        !          2033:                        x_put_long (ad, frame_id);
        !          2034:                        ad += 4;
1.1       root     2035:                } else {
1.1.1.4   root     2036:                        /* 44 (rev $40) and 52 (rev $41) byte 68040 unimplemented instruction frame */
                   2037:                        /* 96 byte 68040 busy frame */
                   2038:                        int frame_size = regs.fpu_exp_state == 2 ? 0x64 : (fpu_version >= 0x41 ? 0x34 : 0x2c);
                   2039:                        uae_u32 frame_id = ((fpu_version << 8) | (frame_size - 4)) << 16;
                   2040: 
1.1.1.6 ! root     2041: #if 0
        !          2042:                        write_log(_T("68040 FSAVE %d (%d), CMDREG=%04X"), regs.fp_exp_pend, frame_size, extra);
        !          2043:                        if (regs.fp_exp_pend == FPU_EXP_UNIMP_DATATYPE_PACKED_PRE) {
        !          2044:                                write_log(_T(" PACKED %08x-%08x-%08x"), fsave_data.pack[0], fsave_data.pack[1], fsave_data.pack[2]);
        !          2045:                        } else if (regs.fp_exp_pend == FPU_EXP_UNIMP_DATATYPE_PACKED_POST) {
        !          2046:                                write_log(_T(" SRC=%s (%08x-%08x-%08x %d)"),
        !          2047:                                        fpp_print(&fsave_data.src), src1[0], src1[1], src1[2], stag);
        !          2048:                                write_log(_T(" DST=%s (%08x-%08x-%08x %d)"),
        !          2049:                                        fpp_print(&fsave_data.dst), src2[0], src2[1], src2[2], dtag);
        !          2050:                         }
1.1.1.4   root     2051: #endif
                   2052: 
                   2053:                        if (incr < 0)
                   2054:                                ad -= frame_size;
1.1.1.6 ! root     2055:                        adp = ad;
1.1.1.4   root     2056:                        x_put_long (ad, frame_id);
1.1       root     2057:                        ad += 4;
1.1.1.4   root     2058:                        if (regs.fpu_exp_state == 2) {
                   2059:                                /* BUSY frame */
                   2060:                                x_put_long(ad, 0);
                   2061:                                ad += 4;
                   2062:                                x_put_long(ad, 0); // CU_SAVEPC (Software shouldn't care)
                   2063:                                ad += 4;
                   2064:                                x_put_long(ad, 0);
                   2065:                                ad += 4;
                   2066:                                x_put_long(ad, 0);
                   2067:                                ad += 4;
                   2068:                                x_put_long(ad, 0);
                   2069:                                ad += 4;
1.1.1.6 ! root     2070:                                x_put_long(ad, fsave_data.wbt[0]); // WBTS/WBTE
1.1.1.4   root     2071:                                ad += 4;
1.1.1.6 ! root     2072:                                x_put_long(ad, fsave_data.wbt[1]); // WBTM
1.1.1.4   root     2073:                                ad += 4;
1.1.1.6 ! root     2074:                                x_put_long(ad, fsave_data.wbt[2]); // WBTM
1.1.1.4   root     2075:                                ad += 4;
                   2076:                                x_put_long(ad, 0);
                   2077:                                ad += 4;
1.1.1.6 ! root     2078:                                x_put_long(ad, fsave_data.fpiarcu); // FPIARCU (same as FPU PC or something else?)
1.1.1.4   root     2079:                                ad += 4;
                   2080:                                x_put_long(ad, 0);
                   2081:                                ad += 4;
                   2082:                                x_put_long(ad, 0);
                   2083:                                ad += 4;
                   2084:                        }
                   2085:                        if (fpu_version >= 0x41 || regs.fpu_exp_state == 2) {
1.1.1.6 ! root     2086:                                x_put_long(ad, fsave_data.cmdreg3b << 16); // CMDREG3B
1.1.1.4   root     2087:                                ad += 4;
                   2088:                                x_put_long (ad, 0);
                   2089:                                ad += 4;
                   2090:                        }
1.1.1.6 ! root     2091:                        x_put_long (ad, (fsave_data.stag << 29) | (fsave_data.wbtm66 << 26) | (fsave_data.grs << 23)); // STAG
1.1.1.4   root     2092:                        ad += 4;
1.1.1.6 ! root     2093:                        x_put_long (ad, fsave_data.cmdreg1b << 16); // CMDREG1B
1.1.1.4   root     2094:                        ad += 4;
1.1.1.6 ! root     2095:                        x_put_long (ad, (fsave_data.dtag << 29) | (fsave_data.wbte15 << 20)); // DTAG
        !          2096:                        ad += 4;
        !          2097:                        x_put_long (ad, (fsave_data.e1 << 26) | (fsave_data.e3 << 25) | (fsave_data.t << 20));
        !          2098:                        ad += 4;
        !          2099:                        x_put_long(ad, fsave_data.fpt[0]); // FPTS/FPTE
        !          2100:                        ad += 4;
        !          2101:                        x_put_long(ad, fsave_data.fpt[1]); // FPTM
        !          2102:                        ad += 4;
        !          2103:                        x_put_long(ad, fsave_data.fpt[2]); // FPTM
        !          2104:                        ad += 4;
        !          2105:                        x_put_long(ad, fsave_data.et[0]); // ETS/ETE
        !          2106:                        ad += 4;
        !          2107:                        x_put_long(ad, fsave_data.et[1]); // ETM
        !          2108:                        ad += 4;
        !          2109:                        x_put_long(ad, fsave_data.et[2]); // ETM
1.1.1.4   root     2110:                        ad += 4;
1.1       root     2111:                }
                   2112:        } else { /* 68881/68882 */
1.1.1.6 ! root     2113:                uae_u32 biu_flags = 0x540effff;
        !          2114:                int frame_size = currprefs.fpu_model == 68882 ? 0x3c : 0x1c;
        !          2115:                uae_u32 frame_id = regs.fpu_state == 0 ? ((frame_size - 4) << 16) : (fpu_version << 24) | ((frame_size - 4) << 16);
1.1.1.5   root     2116:                
1.1.1.6 ! root     2117:                regs.fp_exp_pend = 0;
        !          2118:                if (regs.fpu_exp_state) {
        !          2119:                        biu_flags |= 0x20000000;
        !          2120:                } else {
        !          2121:                        biu_flags |= 0x08000000;
        !          2122:                }
        !          2123:                if (regs.fpu_state == 0)
        !          2124:                        frame_size = 4;
        !          2125: 
1.1.1.4   root     2126:                if (currprefs.mmu_model) {
1.1.1.6 ! root     2127:                        i = 0;
        !          2128:                        if (incr < 0)
        !          2129:                                ad -= frame_size;
        !          2130:                        adp = ad;
        !          2131:                        if(mmu030_state[0] == i) {
        !          2132:                                x_put_long(ad, frame_id); // frame id
        !          2133:                                mmu030_state[0]++;
        !          2134:                        }
        !          2135:                        ad += 4;
        !          2136:                        i++;
        !          2137:                        if (regs.fpu_state != 0) { // idle frame
        !          2138:                                if(mmu030_state[0] == i) {
        !          2139:                                        x_put_long(ad, fsave_data.ccr); // command/condition register
        !          2140:                                        mmu030_state[0]++;
        !          2141:                                }
        !          2142:                                ad += 4;
        !          2143:                                i++;
        !          2144:                                if (currprefs.fpu_model == 68882) {
        !          2145:                                        while (i <= 9) {
        !          2146:                                                if (mmu030_state[0] == i) {
        !          2147:                                                        x_put_long(ad, 0x00000000); // internal
        !          2148:                                                        mmu030_state[0]++;
        !          2149:                                                }
        !          2150:                                                ad += 4;
        !          2151:                                                i++;
1.1.1.4   root     2152:                                        }
                   2153:                                }
1.1.1.6 ! root     2154:                                if (mmu030_state[0] == i) {
        !          2155:                                        x_put_long (ad, fsave_data.eo[0]); // exceptional operand lo
1.1.1.4   root     2156:                                        mmu030_state[0]++;
                   2157:                                }
1.1.1.6 ! root     2158:                                ad += 4;
        !          2159:                                i++;
        !          2160:                                if (mmu030_state[0] == i) {
        !          2161:                                        x_put_long (ad, fsave_data.eo[1]); // exceptional operand mid
1.1.1.4   root     2162:                                        mmu030_state[0]++;
                   2163:                                }
                   2164:                                ad += 4;
1.1.1.6 ! root     2165:                                i++;
        !          2166:                                if (mmu030_state[0] == i) {
        !          2167:                                        x_put_long (ad, fsave_data.eo[2]); // exceptional operand hi
        !          2168:                                        mmu030_state[0]++;
        !          2169:                                }
        !          2170:                                ad += 4;
        !          2171:                                i++;
        !          2172:                                if (mmu030_state[0] == i) {
        !          2173:                                        x_put_long(ad, 0x00000000); // operand register
        !          2174:                                        mmu030_state[0]++;
        !          2175:                                }
        !          2176:                                ad += 4;
        !          2177:                                i++;
        !          2178:                                if (mmu030_state[0] == i) {
        !          2179:                                        x_put_long(ad, biu_flags); // biu flags
        !          2180:                                        mmu030_state[0]++;
1.1.1.4   root     2181:                                }
1.1.1.6 ! root     2182:                                ad += 4;
1.1       root     2183:                        }
                   2184:                } else {
1.1.1.6 ! root     2185:                        if (incr < 0)
        !          2186:                                ad -= frame_size;
        !          2187:                        adp = ad;
        !          2188:                        x_put_long(ad, frame_id); // frame id
        !          2189:                        ad += 4;
        !          2190:                        if (regs.fpu_state != 0) { // idle frame
        !          2191:                                x_put_long(ad, fsave_data.ccr); // command/condition register
1.1       root     2192:                                ad += 4;
1.1.1.6 ! root     2193:                                if(currprefs.fpu_model == 68882) {
        !          2194:                                        for(i = 0; i < 32; i += 4) {
        !          2195:                                                x_put_long(ad, 0x00000000); // internal
        !          2196:                                                ad += 4;
        !          2197:                                        }
1.1.1.4   root     2198:                                }
1.1.1.6 ! root     2199:                                x_put_long(ad, fsave_data.eo[0]); // exceptional operand hi
        !          2200:                                ad += 4;
        !          2201:                                x_put_long(ad, fsave_data.eo[1]); // exceptional operand mid
        !          2202:                                ad += 4;
        !          2203:                                x_put_long(ad, fsave_data.eo[2]); // exceptional operand lo
        !          2204:                                ad += 4;
        !          2205:                                x_put_long(ad, 0x00000000); // operand register
        !          2206:                                ad += 4;
        !          2207:                                x_put_long(ad, biu_flags); // biu flags
        !          2208:                                ad += 4;
1.1       root     2209:                        }
                   2210:                }
                   2211:        }
1.1.1.4   root     2212: 
1.1.1.6 ! root     2213:        if ((opcode & 0x38) == 0x20) // predecrement
        !          2214:                m68k_areg (regs, opcode & 7) = adp;
1.1.1.4   root     2215:        regs.fpu_exp_state = 0;
1.1       root     2216: }
                   2217: 
1.1.1.6 ! root     2218: static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra);
        !          2219: 
1.1       root     2220: void fpuop_restore (uae_u32 opcode)
                   2221: {
1.1.1.6 ! root     2222:        int fpu_version;
        !          2223:        int frame_version;
        !          2224:        int fpu_model = currprefs.fpu_model;
1.1.1.4   root     2225:        uaecptr pc = m68k_getpc () - 2;
1.1.1.6 ! root     2226:        uae_u32 ad, ad_orig;
1.1       root     2227:        uae_u32 d;
                   2228: 
1.1.1.4   root     2229:        regs.fp_exception = false;
1.1.1.6 ! root     2230: 
1.1       root     2231: #if DEBUG_FPP
                   2232:        if (!isinrom ())
1.1.1.4   root     2233:                write_log (_T("frestore_opp at %08x\n"), m68k_getpc ());
1.1       root     2234: #endif
1.1.1.4   root     2235: 
                   2236:        if (fault_if_no_6888x (opcode, 0, pc))
1.1       root     2237:                return;
                   2238: 
                   2239:        if (get_fp_ad (opcode, &ad) == 0) {
1.1.1.4   root     2240:                fpu_op_illg (opcode, 0, pc);
1.1       root     2241:                return;
                   2242:        }
                   2243: 
1.1.1.4   root     2244:        if (fault_if_no_fpu (opcode, 0, ad, pc))
                   2245:                return;
1.1.1.6 ! root     2246:        ad_orig = ad;
1.1.1.4   root     2247:        regs.fpiar = pc;
                   2248: 
1.1.1.6 ! root     2249:        // write_log(_T("FRESTORE %08x %08x\n"), M68K_GETPC, ad);
1.1.1.4   root     2250: 
1.1.1.6 ! root     2251:        // FRESTORE does not support predecrement
        !          2252: 
        !          2253:        d = x_get_long (ad);
        !          2254: 
        !          2255:        frame_version = (d >> 24) & 0xff;
        !          2256: 
        !          2257: retry:
        !          2258:        ad = ad_orig + 4;
        !          2259:        fpu_version = get_fpu_version(fpu_model);
        !          2260:        if (fpu_model == 68060) {
1.1.1.4   root     2261:                int ff = (d >> 8) & 0xff;
1.1.1.6 ! root     2262:                uae_u32 v = d & 0x7;
        !          2263:                fsave_data.eo[0] = d & 0xffff0000;
        !          2264: 
        !          2265:                fsave_data.eo[1] = x_get_long (ad);
        !          2266:                ad += 4;
        !          2267:                fsave_data.eo[2] = x_get_long (ad);
        !          2268:                ad += 4;
1.1.1.4   root     2269: 
                   2270:                if (ff == 0x60) {
                   2271:                        regs.fpu_state = 1;
                   2272:                        regs.fpu_exp_state = 0;
                   2273:                } else if (ff == 0xe0) {
1.1.1.6 ! root     2274:                        regs.fpu_state = 1;
        !          2275:                        regs.fpu_exp_state = 2;
        !          2276:                        if (v == 7) {
        !          2277:                                regs.fp_unimp_pend = 1;
        !          2278:                        } else {
        !          2279:                                regs.fp_exp_pend = 48 + v;
        !          2280:                        }
1.1.1.4   root     2281:                } else if (ff) {
1.1.1.6 ! root     2282:                        write_log (_T("FRESTORE invalid frame format %02x %08x ADDR=%08x\n"), ff, d, ad_orig);
        !          2283:                        Exception(14);
        !          2284:                        return;
        !          2285:                } else {
        !          2286:                        fpu_null();
        !          2287:                }
        !          2288: 
        !          2289:        } else if (fpu_model == 68040) {
        !          2290: 
        !          2291:                 if (frame_version == fpu_version) { // not null frame
        !          2292:                        uae_u32 frame_size = (d >> 16) & 0xff;
        !          2293: 
        !          2294:                        if (frame_size == 0x60) { // busy
        !          2295:                                fpdata src, dst;
        !          2296:                                uae_u32 tmp, v, opclass, cmdreg1b, fpte15, et15, cusavepc;
        !          2297: 
        !          2298:                                ad += 0x4; // offset to CU_SAVEPC field
        !          2299:                                tmp = x_get_long (ad);
        !          2300:                                cusavepc = tmp >> 24;
        !          2301:                                ad += 0x20; // offset to FPIARCU field
        !          2302:                                regs.fpiar = x_get_long (ad);
        !          2303:                                ad += 0x14; // offset to ET15 field
        !          2304:                                tmp = x_get_long (ad);
        !          2305:                                et15 = (tmp & 0x10000000) >> 28;
        !          2306:                                ad += 0x4; // offset to CMDREG1B field
        !          2307:                                fsave_data.cmdreg1b = x_get_long (ad);
        !          2308:                                fsave_data.cmdreg1b >>= 16;
        !          2309:                                cmdreg1b = fsave_data.cmdreg1b;
        !          2310:                                ad += 0x4; // offset to FPTE15 field
        !          2311:                                tmp = x_get_long (ad);
        !          2312:                                fpte15 = (tmp & 0x10000000) >> 28;
        !          2313:                                ad += 0x8; // offset to FPTE field
        !          2314:                                fsave_data.fpt[0] = x_get_long (ad);
        !          2315:                                ad += 0x4;
        !          2316:                                fsave_data.fpt[1] = x_get_long (ad);
        !          2317:                                ad += 0x4;
        !          2318:                                fsave_data.fpt[2] = x_get_long (ad);
        !          2319:                                ad += 0x4; // offset to ET field
        !          2320:                                fsave_data.et[0] = x_get_long (ad);
        !          2321:                                ad += 0x4;
        !          2322:                                fsave_data.et[1] = x_get_long (ad);
        !          2323:                                ad += 0x4;
        !          2324:                                fsave_data.et[2] = x_get_long (ad);
        !          2325:                                ad += 0x4;
        !          2326:                                
        !          2327:                                opclass = (cmdreg1b >> 13) & 0x7; // just to be sure
        !          2328:                                
        !          2329:                                if (cusavepc == 0xFE) {
        !          2330:                                        if (opclass == 0 || opclass == 2) {
        !          2331:                                                fpp_to_exten_fmovem(&dst, fsave_data.fpt[0], fsave_data.fpt[1], fsave_data.fpt[2]);
        !          2332:                                                fpp_denormalize(&dst, fpte15);
        !          2333:                                                fpp_to_exten_fmovem(&src, fsave_data.et[0], fsave_data.et[1], fsave_data.et[2]);
        !          2334:                                                fpp_denormalize(&src, et15);
        !          2335: #if EXCEPTION_FPP
        !          2336:                                                uae_u32 tmpsrc[3], tmpdst[3];
        !          2337:                                                fpp_from_exten_fmovem(&src, &tmpsrc[0], &tmpsrc[1], &tmpsrc[2]);
        !          2338:                                                fpp_from_exten_fmovem(&dst, &tmpdst[0], &tmpdst[1], &tmpdst[2]);
        !          2339:                                                write_log (_T("FRESTORE src = %08X %08X %08X, dst = %08X %08X %08X, extra = %04X\n"),
        !          2340:                                                                   tmpsrc[0], tmpsrc[1], tmpsrc[2], tmpdst[0], tmpdst[1], tmpdst[2], cmdreg1b);
        !          2341: #endif
        !          2342:                                                fpsr_clear_status();
        !          2343:                                                
        !          2344:                                                v = fp_arithmetic(&src, &dst, cmdreg1b);
        !          2345:                                                
        !          2346:                                                if (v)
        !          2347:                                                        regs.fp[(cmdreg1b>>7)&7] = dst;
        !          2348:                                                
        !          2349:                                                fpsr_check_arithmetic_exception(0, &src, regs.fp_opword, cmdreg1b, regs.fp_ea);
        !          2350:                                        } else {
        !          2351:                                                write_log (_T("FRESTORE resume of opclass %d instruction not supported %08x\n"), opclass, ad_orig);
        !          2352:                                        }
        !          2353:                                }
        !          2354: 
        !          2355:                        } else if (frame_size == 0x30 || frame_size == 0x28) { // unimp
        !          2356: 
        !          2357:                                // TODO: restore frame contents
        !          2358:                                ad += frame_size;
        !          2359: 
        !          2360:                        } else if (frame_size == 0x00) { // idle
        !          2361:                                regs.fpu_state = 1;
        !          2362:                                regs.fpu_exp_state = 0;
        !          2363:                        } else {
        !          2364:                                write_log (_T("FRESTORE invalid frame size %02x %08x %08x\n"), frame_size, d, ad_orig);
        !          2365: 
        !          2366:                                Exception(14);
        !          2367:                                return;
        !          2368: 
        !          2369:                        }
        !          2370:                } else if (frame_version == 0x00) { // null frame
        !          2371:                        fpu_null();
1.1.1.4   root     2372:                } else {
1.1.1.6 ! root     2373:                        if (!currprefs.fpu_no_unimplemented && frame_version == 0x1f && currprefs.fpu_model == fpu_model) {
        !          2374:                                // horrible hack to support on the fly 6888x <> 68040 FPU switching
        !          2375:                                fpu_model = 68881;
        !          2376:                                goto retry;
        !          2377:                        }
        !          2378:                        write_log (_T("FRESTORE 68040 (%d) invalid frame version %02x %08x %08x\n"), fpu_model, frame_version, d, ad_orig);
        !          2379:                        Exception(14);
        !          2380:                        return;
1.1.1.4   root     2381:                }
1.1.1.6 ! root     2382: 
1.1.1.4   root     2383:        } else {
1.1.1.6 ! root     2384: 
        !          2385:                // 6888x
        !          2386:                if (frame_version == fpu_version) { // not null frame
        !          2387:                        uae_u32 biu_flags;
        !          2388:                        uae_u32 frame_size = (d >> 16) & 0xff;
        !          2389:                        uae_u32 biu_offset = frame_size - 4;
1.1.1.4   root     2390:                        regs.fpu_state = 1;
1.1.1.6 ! root     2391: 
        !          2392:                        if (frame_size == 0x18 || frame_size == 0x38) { // idle
        !          2393:                                fsave_data.ccr = x_get_long (ad);
        !          2394:                                ad += 4;
        !          2395:                                // 68882 internal registers (32 bytes, unused)
        !          2396:                                ad += frame_size - 24;
        !          2397:                                fsave_data.eo[0] = x_get_long (ad);
        !          2398:                                ad += 4;
        !          2399:                                fsave_data.eo[1] = x_get_long (ad);
        !          2400:                                ad += 4;
        !          2401:                                fsave_data.eo[2] = x_get_long (ad);
        !          2402:                                ad += 4;
        !          2403:                                // operand register (unused)
        !          2404:                                ad += 4;
        !          2405:                                biu_flags = x_get_long (ad);
        !          2406:                                ad += 4;
        !          2407:                                
        !          2408:                                if ((biu_flags & 0x08000000) == 0x00000000) {
        !          2409:                                        regs.fpu_exp_state = 2;
        !          2410:                                        regs.fp_exp_pend = fpsr_get_vector(regs.fpsr & regs.fpcr & 0xff00);
        !          2411:                                } else {
        !          2412:                                        regs.fpu_exp_state = 0;
        !          2413:                                        regs.fp_exp_pend = 0;
        !          2414:                                }
        !          2415:                        } else if (frame_size == 0xB4 || frame_size == 0xD4) {
        !          2416:                                write_log (_T("FRESTORE of busy frame not supported %08x\n"), ad_orig);
        !          2417:                                ad += frame_size;
        !          2418:                        } else {
        !          2419:                                write_log (_T("FRESTORE invalid frame size %02x %08x %08x\n"), frame_size, d, ad_orig);
        !          2420:                                Exception(14);
        !          2421:                                return;
        !          2422:                        }
        !          2423:                } else if (frame_version == 0x00) { // null frame
        !          2424:                        fpu_null();
1.1.1.4   root     2425:                } else {
1.1.1.6 ! root     2426:                        if (!currprefs.fpu_no_unimplemented && (frame_version == 0x40 || frame_version == 0x41) && currprefs.fpu_model == fpu_model) {
        !          2427:                                // horrible hack to support on the fly 6888x <> 68040 FPU switching
        !          2428:                                fpu_model = 68040;
        !          2429:                                goto retry;
        !          2430:                        }
        !          2431:                        write_log (_T("FRESTORE 6888x (%d) invalid frame version %02x %08x %08x\n"), fpu_model, frame_version, d, ad_orig);
        !          2432:                        Exception(14);
        !          2433:                        return;
1.1.1.4   root     2434:                }
                   2435:        }
1.1       root     2436: 
1.1.1.6 ! root     2437:        if ((opcode & 0x38) == 0x18) /// postincrement
1.1.1.4   root     2438:                m68k_areg (regs, opcode & 7) = ad;
1.1.1.6 ! root     2439: 
        !          2440:        fp_exception_pending(false);
1.1.1.4   root     2441: }
                   2442: 
                   2443: static uaecptr fmovem2mem (uaecptr ad, uae_u32 list, int incr, int regdir)
                   2444: {
                   2445:        int reg;
                   2446: 
                   2447:        // 68030 MMU state saving is annoying!
                   2448:        if (currprefs.mmu_model == 68030) {
                   2449:                int idx = 0;
                   2450:                int r;
                   2451:                int i;
                   2452:                uae_u32 wrd[3];
                   2453:                mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM1;
                   2454:                for (r = 0; r < 8; r++) {
                   2455:                        if (regdir < 0)
                   2456:                                reg = 7 - r;
                   2457:                        else
                   2458:                                reg = r;
                   2459:                        if (list & 0x80) {
1.1.1.6 ! root     2460:                                fpp_from_exten_fmovem(&regs.fp[reg], &wrd[0], &wrd[1], &wrd[2]);
1.1.1.4   root     2461:                                if (incr < 0)
                   2462:                                        ad -= 3 * 4;
                   2463:                                for (i = 0; i < 3; i++) {
                   2464:                                        if (mmu030_state[0] == idx * 3 + i) {
                   2465:                                                if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM2) {
                   2466:                                                        mmu030_state[1] &= ~MMU030_STATEFLAG1_MOVEM2;
                   2467:                                                }
                   2468:                                                else {
                   2469:                                                        mmu030_data_buffer = wrd[i];
                   2470:                                                        x_put_long(ad + i * 4, wrd[i]);
                   2471:                                                }
                   2472:                                                mmu030_state[0]++;
                   2473:                                        }
1.1       root     2474:                                }
1.1.1.4   root     2475:                                if (incr > 0)
                   2476:                                        ad += 3 * 4;
                   2477:                                idx++;
1.1       root     2478:                        }
1.1.1.4   root     2479:                        list <<= 1;
                   2480:                }
                   2481:        } else {
                   2482:                int r;
                   2483:                for (r = 0; r < 8; r++) {
                   2484:                        uae_u32 wrd1, wrd2, wrd3;
                   2485:                        if (regdir < 0)
                   2486:                                reg = 7 - r;
                   2487:                        else
                   2488:                                reg = r;
                   2489:                        if (list & 0x80) {
1.1.1.6 ! root     2490:                                fpp_from_exten_fmovem(&regs.fp[reg], &wrd1, &wrd2, &wrd3);
1.1.1.4   root     2491:                                if (incr < 0)
                   2492:                                        ad -= 3 * 4;
                   2493:                                x_put_long(ad + 0, wrd1);
                   2494:                                x_put_long(ad + 4, wrd2);
                   2495:                                x_put_long(ad + 8, wrd3);
                   2496:                                if (incr > 0)
                   2497:                                        ad += 3 * 4;
                   2498:                        }
                   2499:                        list <<= 1;
                   2500:                }
                   2501:        }
                   2502:        return ad;
                   2503: }
                   2504: 
                   2505: static uaecptr fmovem2fpp (uaecptr ad, uae_u32 list, int incr, int regdir)
                   2506: {
                   2507:        int reg;
                   2508: 
                   2509:        if (currprefs.mmu_model == 68030) {
                   2510:                uae_u32 wrd[3];
                   2511:                int idx = 0;
                   2512:                int r;
                   2513:                int i;
                   2514:                mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM1 | MMU030_STATEFLAG1_FMOVEM;
                   2515:                if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM2)
                   2516:                        ad = mmu030_ad[mmu030_idx].val;
                   2517:                else
                   2518:                        mmu030_ad[mmu030_idx].val = ad;
                   2519:                for (r = 0; r < 8; r++) {
                   2520:                        if (regdir < 0)
                   2521:                                reg = 7 - r;
                   2522:                        else
                   2523:                                reg = r;
                   2524:                        if (list & 0x80) {
                   2525:                                if (incr < 0)
                   2526:                                        ad -= 3 * 4;
                   2527:                                for (i = 0; i < 3; i++) {
                   2528:                                        if (mmu030_state[0] == idx * 3 + i) {
                   2529:                                                if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM2) {
                   2530:                                                        mmu030_state[1] &= ~MMU030_STATEFLAG1_MOVEM2;
                   2531:                                                        wrd[i] = mmu030_data_buffer;
                   2532:                                                } else {
                   2533:                                                        wrd[i] = x_get_long (ad + i * 4);
                   2534:                                                }
                   2535:                                                // save first two entries if 2nd or 3rd get_long() faults.
                   2536:                                                if (i == 0 || i == 1)
                   2537:                                                        mmu030_fmovem_store[i] = wrd[i];
                   2538:                                                mmu030_state[0]++;
                   2539:                                                if (i == 2)
1.1.1.6 ! root     2540:                                                        fpp_to_exten (&regs.fp[reg], mmu030_fmovem_store[0], mmu030_fmovem_store[1], wrd[2]);
1.1.1.4   root     2541:                                        }
1.1       root     2542:                                }
1.1.1.4   root     2543:                                if (incr > 0)
                   2544:                                        ad += 3 * 4;
                   2545:                                idx++;
1.1       root     2546:                        }
1.1.1.4   root     2547:                        list <<= 1;
1.1       root     2548:                }
1.1.1.4   root     2549:        } else {
                   2550:                int r;
                   2551:                for (r = 0; r < 8; r++) {
                   2552:                        uae_u32 wrd1, wrd2, wrd3;
                   2553:                        if (regdir < 0)
                   2554:                                reg = 7 - r;
                   2555:                        else
                   2556:                                reg = r;
                   2557:                        if (list & 0x80) {
                   2558:                                if (incr < 0)
                   2559:                                        ad -= 3 * 4;
                   2560:                                wrd1 = x_get_long (ad + 0);
                   2561:                                wrd2 = x_get_long (ad + 4);
                   2562:                                wrd3 = x_get_long (ad + 8);
                   2563:                                if (incr > 0)
                   2564:                                        ad += 3 * 4;
1.1.1.6 ! root     2565:                                fpp_to_exten (&regs.fp[reg], wrd1, wrd2, wrd3);
1.1       root     2566:                        }
1.1.1.4   root     2567:                        list <<= 1;
                   2568:                }
                   2569:        }
                   2570:        return ad;
                   2571: }
                   2572: 
1.1.1.6 ! root     2573: static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra)
1.1.1.4   root     2574: {
1.1.1.6 ! root     2575:        uae_u64 q = 0;
        !          2576:        uae_u8 s = 0;
1.1.1.4   root     2577: 
                   2578:        switch (extra & 0x7f)
                   2579:        {
                   2580:                case 0x00: /* FMOVE */
1.1.1.6 ! root     2581:                        fpp_move(dst, src, 0);
        !          2582:                        break;
        !          2583:                case 0x40: /* FSMOVE */
        !          2584:                        fpp_move(dst, src, 32);
        !          2585:                        break;
        !          2586:                case 0x44: /* FDMOVE */
        !          2587:                        fpp_move(dst, src, 64);
1.1.1.4   root     2588:                        break;
                   2589:                case 0x01: /* FINT */
1.1.1.6 ! root     2590:                        fpp_int(dst, src);
1.1.1.4   root     2591:                        break;
                   2592:                case 0x02: /* FSINH */
1.1.1.6 ! root     2593:                        fpp_sinh(dst, src);
1.1.1.4   root     2594:                        break;
                   2595:                case 0x03: /* FINTRZ */
1.1.1.6 ! root     2596:                        fpp_intrz(dst, src);
1.1.1.4   root     2597:                        break;
                   2598:                case 0x04: /* FSQRT */
1.1.1.6 ! root     2599:                        fpp_sqrt(dst, src, 0);
        !          2600:                        break;
1.1.1.4   root     2601:                case 0x41: /* FSSQRT */
1.1.1.6 ! root     2602:                        fpp_sqrt(dst, src,  32);
        !          2603:                        break;
1.1.1.4   root     2604:                case 0x45: /* FDSQRT */
1.1.1.6 ! root     2605:                        fpp_sqrt(dst, src, 64);
1.1.1.4   root     2606:                        break;
                   2607:                case 0x06: /* FLOGNP1 */
1.1.1.6 ! root     2608:                        fpp_lognp1(dst, src);
1.1.1.4   root     2609:                        break;
                   2610:                case 0x08: /* FETOXM1 */
1.1.1.6 ! root     2611:                        fpp_etoxm1(dst, src);
1.1.1.4   root     2612:                        break;
                   2613:                case 0x09: /* FTANH */
1.1.1.6 ! root     2614:                        fpp_tanh(dst, src);
1.1.1.4   root     2615:                        break;
                   2616:                case 0x0a: /* FATAN */
1.1.1.6 ! root     2617:                        fpp_atan(dst, src);
1.1.1.4   root     2618:                        break;
                   2619:                case 0x0c: /* FASIN */
1.1.1.6 ! root     2620:                        fpp_asin(dst, src);
1.1.1.4   root     2621:                        break;
                   2622:                case 0x0d: /* FATANH */
1.1.1.6 ! root     2623:                        fpp_atanh(dst, src);
1.1.1.4   root     2624:                        break;
                   2625:                case 0x0e: /* FSIN */
1.1.1.6 ! root     2626:                        fpp_sin(dst, src);
1.1.1.4   root     2627:                        break;
                   2628:                case 0x0f: /* FTAN */
1.1.1.6 ! root     2629:                        fpp_tan(dst, src);
1.1.1.4   root     2630:                        break;
                   2631:                case 0x10: /* FETOX */
1.1.1.6 ! root     2632:                        fpp_etox(dst, src);
1.1.1.4   root     2633:                        break;
                   2634:                case 0x11: /* FTWOTOX */
1.1.1.6 ! root     2635:                        fpp_twotox(dst, src);
1.1.1.4   root     2636:                        break;
                   2637:                case 0x12: /* FTENTOX */
1.1.1.6 ! root     2638:                        fpp_tentox(dst, src);
1.1.1.4   root     2639:                        break;
                   2640:                case 0x14: /* FLOGN */
1.1.1.6 ! root     2641:                        fpp_logn(dst, src);
1.1.1.4   root     2642:                        break;
                   2643:                case 0x15: /* FLOG10 */
1.1.1.6 ! root     2644:                        fpp_log10(dst, src);
1.1.1.4   root     2645:                        break;
                   2646:                case 0x16: /* FLOG2 */
1.1.1.6 ! root     2647:                        fpp_log2(dst, src);
1.1.1.4   root     2648:                        break;
                   2649:                case 0x18: /* FABS */
1.1.1.6 ! root     2650:                        fpp_abs(dst, src, 0);
        !          2651:                        break;
1.1.1.4   root     2652:                case 0x58: /* FSABS */
1.1.1.6 ! root     2653:                        fpp_abs(dst, src, 32);
        !          2654:                        break;
1.1.1.4   root     2655:                case 0x5c: /* FDABS */
1.1.1.6 ! root     2656:                        fpp_abs(dst, src, 64);
1.1.1.4   root     2657:                        break;
                   2658:                case 0x19: /* FCOSH */
1.1.1.6 ! root     2659:                        fpp_cosh(dst, src);
1.1.1.4   root     2660:                        break;
                   2661:                case 0x1a: /* FNEG */
1.1.1.6 ! root     2662:                        fpp_neg(dst, src, 0);
        !          2663:                        break;
1.1.1.4   root     2664:                case 0x5a: /* FSNEG */
1.1.1.6 ! root     2665:                        fpp_neg(dst, src, 32);
        !          2666:                        break;
1.1.1.4   root     2667:                case 0x5e: /* FDNEG */
1.1.1.6 ! root     2668:                        fpp_neg(dst, src, 64);
1.1.1.4   root     2669:                        break;
                   2670:                case 0x1c: /* FACOS */
1.1.1.6 ! root     2671:                        fpp_acos(dst, src);
1.1.1.4   root     2672:                        break;
                   2673:                case 0x1d: /* FCOS */
1.1.1.6 ! root     2674:                        fpp_cos(dst, src);
1.1.1.4   root     2675:                        break;
                   2676:                case 0x1e: /* FGETEXP */
1.1.1.6 ! root     2677:                        fpp_getexp(dst, src);
1.1.1.4   root     2678:                        break;
                   2679:                case 0x1f: /* FGETMAN */
1.1.1.6 ! root     2680:                        fpp_getman(dst, src);
1.1.1.4   root     2681:                        break;
                   2682:                case 0x20: /* FDIV */
1.1.1.6 ! root     2683:                        fpp_div(dst, src, 0);
        !          2684:                        break;
1.1.1.4   root     2685:                case 0x60: /* FSDIV */
1.1.1.6 ! root     2686:                        fpp_div(dst, src, 32);
        !          2687:                        break;
1.1.1.4   root     2688:                case 0x64: /* FDDIV */
1.1.1.6 ! root     2689:                        fpp_div(dst, src, 64);
1.1.1.4   root     2690:                        break;
                   2691:                case 0x21: /* FMOD */
1.1.1.6 ! root     2692:                        fpsr_get_quotient(&q, &s);
        !          2693:                        fpp_mod(dst, src, &q, &s);
        !          2694:                        fpsr_set_quotient(q, s);
1.1.1.4   root     2695:                        break;
                   2696:                case 0x22: /* FADD */
1.1.1.6 ! root     2697:                        fpp_add(dst, src, 0);
        !          2698:                        break;
1.1.1.4   root     2699:                case 0x62: /* FSADD */
1.1.1.6 ! root     2700:                        fpp_add(dst, src, 32);
        !          2701:                        break;
1.1.1.4   root     2702:                case 0x66: /* FDADD */
1.1.1.6 ! root     2703:                        fpp_add(dst, src, 64);
1.1.1.4   root     2704:                        break;
                   2705:                case 0x23: /* FMUL */
1.1.1.6 ! root     2706:                        fpp_mul(dst, src, 0);
        !          2707:                        break;
1.1.1.4   root     2708:                case 0x63: /* FSMUL */
1.1.1.6 ! root     2709:                        fpp_mul(dst, src, 32);
        !          2710:                        break;
1.1.1.4   root     2711:                case 0x67: /* FDMUL */
1.1.1.6 ! root     2712:                        fpp_mul(dst, src, 64);
1.1.1.4   root     2713:                        break;
                   2714:                case 0x24: /* FSGLDIV */
1.1.1.6 ! root     2715:                        fpp_sgldiv(dst, src);
1.1.1.4   root     2716:                        break;
                   2717:                case 0x25: /* FREM */
1.1.1.6 ! root     2718:                        fpsr_get_quotient(&q, &s);
        !          2719:                        fpp_rem(dst, src, &q, &s);
        !          2720:                        fpsr_set_quotient(q, s);
1.1.1.4   root     2721:                        break;
                   2722:                case 0x26: /* FSCALE */
1.1.1.6 ! root     2723:                        fpp_scale(dst, src);
1.1.1.4   root     2724:                        break;
                   2725:                case 0x27: /* FSGLMUL */
1.1.1.6 ! root     2726:                        fpp_sglmul(dst, src);
1.1.1.4   root     2727:                        break;
                   2728:                case 0x28: /* FSUB */
1.1.1.6 ! root     2729:                        fpp_sub(dst, src, 0);
1.1.1.4   root     2730:                        break;
                   2731:                case 0x68: /* FSSUB */
1.1.1.6 ! root     2732:                        fpp_sub(dst, src, 32);
1.1.1.4   root     2733:                        break;
1.1.1.6 ! root     2734:                case 0x6c: /* FDSUB */
        !          2735:                        fpp_sub(dst, src, 64);
1.1.1.4   root     2736:                        break;
                   2737:                case 0x30: /* FSINCOS */
                   2738:                case 0x31: /* FSINCOS */
                   2739:                case 0x32: /* FSINCOS */
                   2740:                case 0x33: /* FSINCOS */
                   2741:                case 0x34: /* FSINCOS */
                   2742:                case 0x35: /* FSINCOS */
                   2743:                case 0x36: /* FSINCOS */
                   2744:                case 0x37: /* FSINCOS */
1.1.1.6 ! root     2745:                        fpp_cos(dst, src);
        !          2746:                        regs.fp[extra & 7] = *dst;
        !          2747:                        fpp_sin(dst, src);
1.1.1.4   root     2748:                        break;
1.1.1.6 ! root     2749:                case 0x38: /* FCMP */
        !          2750:                {
        !          2751:                        fpp_cmp(dst, src);
        !          2752:                        fpsr_make_status();
        !          2753:                        fpsr_set_result(dst);
        !          2754:                        return false;
        !          2755:                }
        !          2756:                case 0x3a: /* FTST */
        !          2757:                {
        !          2758:                        fpp_tst(dst, src);
        !          2759:                        fpsr_make_status();
        !          2760:                        fpsr_set_result(dst);
        !          2761:                        return false;
        !          2762:                }
        !          2763:                default:
        !          2764:                        write_log (_T("Unknown FPU arithmetic function (%02x)\n"), extra & 0x7f);
        !          2765:                        return false;
1.1       root     2766:        }
1.1.1.6 ! root     2767: 
        !          2768:        fpsr_set_result(dst);
        !          2769: 
        !          2770:        if (fpsr_make_status())
        !          2771:                return false;
        !          2772: 
1.1.1.4   root     2773:        return true;
1.1       root     2774: }
                   2775: 
1.1.1.4   root     2776: static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
                   2777: {
                   2778:        int reg = -1;
                   2779:        int v;
1.1.1.6 ! root     2780:        fpdata src, dst;
1.1.1.4   root     2781:        uaecptr pc = m68k_getpc () - 4;
                   2782:        uaecptr ad = 0;
1.1       root     2783: 
                   2784: #if DEBUG_FPP
                   2785:        if (!isinrom ())
1.1.1.4   root     2786:                write_log (_T("FPP %04x %04x at %08x\n"), opcode & 0xffff, extra, pc);
1.1       root     2787: #endif
1.1.1.4   root     2788:        if (fault_if_no_6888x (opcode, extra, pc))
1.1       root     2789:                return;
                   2790: 
1.1.1.4   root     2791:        switch ((extra >> 13) & 0x7)
                   2792:        {
1.1       root     2793:                case 3:
1.1.1.6 ! root     2794:                        if (fp_exception_pending(true))
        !          2795:                                return;
        !          2796: 
        !          2797:                        regs.fpiar = pc;
        !          2798:                        fpsr_clear_status();
        !          2799:                        src = regs.fp[(extra >> 7) & 7];
        !          2800:                        v = put_fp_value (&src, opcode, extra, pc, &ad);
        !          2801:                        if (v <= 0) {
        !          2802:                                if (v == 0)
        !          2803:                                        fpu_noinst (opcode, pc);
        !          2804:                                return;
        !          2805:                        }
        !          2806:                        fpsr_make_status();
        !          2807:                        fpsr_check_arithmetic_exception(0, &src, opcode, extra, ad);
        !          2808:                        fp_exception_pending(false); // post/mid instruction
1.1       root     2809:                        return;
                   2810: 
                   2811:                case 4:
                   2812:                case 5:
                   2813:                        if ((opcode & 0x38) == 0) {
1.1.1.4   root     2814:                                if (fault_if_no_fpu (opcode, extra, 0, pc))
                   2815:                                        return;
1.1       root     2816:                                if (extra & 0x2000) {
                   2817:                                        if (extra & 0x1000)
                   2818:                                                m68k_dreg (regs, opcode & 7) = regs.fpcr & 0xffff;
                   2819:                                        if (extra & 0x0800)
1.1.1.4   root     2820:                                                m68k_dreg (regs, opcode & 7) = fpp_get_fpsr ();
1.1       root     2821:                                        if (extra & 0x0400)
                   2822:                                                m68k_dreg (regs, opcode & 7) = regs.fpiar;
                   2823:                                } else {
1.1.1.6 ! root     2824:                                        if (extra & 0x1000)
        !          2825:                                                fpp_set_fpcr(m68k_dreg (regs, opcode & 7));
1.1       root     2826:                                        if (extra & 0x0800)
1.1.1.6 ! root     2827:                                                fpp_set_fpsr(m68k_dreg (regs, opcode & 7));
1.1       root     2828:                                        if (extra & 0x0400)
                   2829:                                                regs.fpiar = m68k_dreg (regs, opcode & 7);
                   2830:                                }
                   2831:                        } else if ((opcode & 0x38) == 0x08) {
1.1.1.4   root     2832:                                if (fault_if_no_fpu (opcode, extra, 0, pc))
                   2833:                                        return;
1.1       root     2834:                                if (extra & 0x2000) {
                   2835:                                        if (extra & 0x1000)
                   2836:                                                m68k_areg (regs, opcode & 7) = regs.fpcr & 0xffff;
                   2837:                                        if (extra & 0x0800)
1.1.1.4   root     2838:                                                m68k_areg (regs, opcode & 7) = fpp_get_fpsr ();
1.1       root     2839:                                        if (extra & 0x0400)
                   2840:                                                m68k_areg (regs, opcode & 7) = regs.fpiar;
                   2841:                                } else {
1.1.1.6 ! root     2842:                                        if (extra & 0x1000)
        !          2843:                                                fpp_set_fpcr(m68k_areg (regs, opcode & 7));
1.1       root     2844:                                        if (extra & 0x0800)
1.1.1.6 ! root     2845:                                                fpp_set_fpsr(m68k_areg (regs, opcode & 7));
1.1       root     2846:                                        if (extra & 0x0400)
                   2847:                                                regs.fpiar = m68k_areg (regs, opcode & 7);
                   2848:                                }
                   2849:                        } else if ((opcode & 0x3f) == 0x3c) {
                   2850:                                if ((extra & 0x2000) == 0) {
1.1.1.4   root     2851:                                        uae_u32 ext[3];
                   2852:                                        // 68060 FMOVEM.L #imm,more than 1 control register: unimplemented EA
                   2853:                                        uae_u16 bits = extra & (0x1000 | 0x0800 | 0x0400);
                   2854:                                        if (bits && bits != 0x1000 && bits != 0x0800 && bits != 0x400) {
1.1.1.6 ! root     2855:                                                if (fault_if_60())
1.1.1.4   root     2856:                                                        return;
                   2857:                                        }
                   2858:                                        // fetch first, use only after all data has been fetched
                   2859:                                        ext[0] = ext[1] = ext[2] = 0;
                   2860:                                        if (extra & 0x1000)
                   2861:                                                ext[0] = x_cp_next_ilong ();
                   2862:                                        if (extra & 0x0800)
                   2863:                                                ext[1] = x_cp_next_ilong ();
                   2864:                                        if (extra & 0x0400)
                   2865:                                                ext[2] = x_cp_next_ilong ();
1.1.1.6 ! root     2866:                                        if (fault_if_no_fpu (opcode, extra, 0, pc))
        !          2867:                                                return;
        !          2868:                                        if (extra & 0x1000)
        !          2869:                                                fpp_set_fpcr(ext[0]);
1.1       root     2870:                                        if (extra & 0x0800)
1.1.1.6 ! root     2871:                                                fpp_set_fpsr(ext[1]);
1.1       root     2872:                                        if (extra & 0x0400)
1.1.1.4   root     2873:                                                regs.fpiar = ext[2];
1.1.1.6 ! root     2874:                                } else {
        !          2875:                                        // immediate as destination
        !          2876:                                        fpu_noinst (opcode, pc);
        !          2877:                                        return;
1.1       root     2878:                                }
                   2879:                        } else if (extra & 0x2000) {
                   2880:                                /* FMOVEM FPP->memory */
                   2881:                                uae_u32 ad;
                   2882:                                int incr = 0;
                   2883: 
                   2884:                                if (get_fp_ad (opcode, &ad) == 0) {
1.1.1.4   root     2885:                                        fpu_noinst (opcode, pc);
1.1       root     2886:                                        return;
                   2887:                                }
1.1.1.4   root     2888:                                if (fault_if_no_fpu (opcode, extra, ad, pc))
                   2889:                                        return;
                   2890: 
1.1       root     2891:                                if ((opcode & 0x38) == 0x20) {
                   2892:                                        if (extra & 0x1000)
                   2893:                                                incr += 4;
                   2894:                                        if (extra & 0x0800)
                   2895:                                                incr += 4;
                   2896:                                        if (extra & 0x0400)
                   2897:                                                incr += 4;
                   2898:                                }
                   2899:                                ad -= incr;
                   2900:                                if (extra & 0x1000) {
1.1.1.4   root     2901:                                        x_cp_put_long (ad, regs.fpcr & 0xffff);
1.1       root     2902:                                        ad += 4;
                   2903:                                }
                   2904:                                if (extra & 0x0800) {
1.1.1.4   root     2905:                                        x_cp_put_long (ad, fpp_get_fpsr ());
1.1       root     2906:                                        ad += 4;
                   2907:                                }
                   2908:                                if (extra & 0x0400) {
1.1.1.4   root     2909:                                        x_cp_put_long (ad, regs.fpiar);
1.1       root     2910:                                        ad += 4;
                   2911:                                }
                   2912:                                ad -= incr;
                   2913:                                if ((opcode & 0x38) == 0x18)
                   2914:                                        m68k_areg (regs, opcode & 7) = ad;
                   2915:                                if ((opcode & 0x38) == 0x20)
                   2916:                                        m68k_areg (regs, opcode & 7) = ad;
                   2917:                        } else {
                   2918:                                /* FMOVEM memory->FPP */
                   2919:                                uae_u32 ad;
                   2920:                                int incr = 0;
                   2921: 
                   2922:                                if (get_fp_ad (opcode, &ad) == 0) {
1.1.1.4   root     2923:                                        fpu_noinst (opcode, pc);
1.1       root     2924:                                        return;
                   2925:                                }
1.1.1.4   root     2926:                                if (fault_if_no_fpu (opcode, extra, ad, pc))
                   2927:                                        return;
                   2928: 
1.1       root     2929:                                if((opcode & 0x38) == 0x20) {
                   2930:                                        if (extra & 0x1000)
                   2931:                                                incr += 4;
                   2932:                                        if (extra & 0x0800)
                   2933:                                                incr += 4;
                   2934:                                        if (extra & 0x0400)
                   2935:                                                incr += 4;
                   2936:                                        ad = ad - incr;
                   2937:                                }
                   2938:                                if (extra & 0x1000) {
1.1.1.6 ! root     2939:                                        fpp_set_fpcr(x_cp_get_long (ad));
1.1       root     2940:                                        ad += 4;
                   2941:                                }
                   2942:                                if (extra & 0x0800) {
1.1.1.6 ! root     2943:                                        fpp_set_fpsr(x_cp_get_long (ad));
1.1       root     2944:                                        ad += 4;
                   2945:                                }
                   2946:                                if (extra & 0x0400) {
1.1.1.4   root     2947:                                        regs.fpiar = x_cp_get_long (ad);
1.1       root     2948:                                        ad += 4;
                   2949:                                }
                   2950:                                if ((opcode & 0x38) == 0x18)
                   2951:                                        m68k_areg (regs, opcode & 7) = ad;
                   2952:                                if ((opcode & 0x38) == 0x20)
                   2953:                                        m68k_areg (regs, opcode & 7) = ad - incr;
                   2954:                        }
                   2955:                        return;
                   2956: 
                   2957:                case 6:
                   2958:                case 7:
                   2959:                        {
                   2960:                                uae_u32 ad, list = 0;
1.1.1.4   root     2961:                                int incr = 1;
                   2962:                                int regdir = 1;
                   2963:                                if (get_fp_ad (opcode, &ad) == 0) {
                   2964:                                        fpu_noinst (opcode, pc);
                   2965:                                        return;
                   2966:                                }
                   2967:                                if (fault_if_no_fpu (opcode, extra, ad, pc))
                   2968:                                        return;
                   2969:                                switch ((extra >> 11) & 3)
                   2970:                                {
                   2971:                                        case 0: /* static pred */
                   2972:                                        case 2: /* static postinc */
                   2973:                                                list = extra & 0xff;
                   2974:                                                break;
1.1.1.6 ! root     2975:                                        case 1: /* dynamic pred */
1.1.1.4   root     2976:                                        case 3: /* dynamic postinc */
1.1.1.6 ! root     2977:                                                if (fault_if_60())
1.1.1.4   root     2978:                                                        return;
                   2979:                                                list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
                   2980:                                                break;
                   2981:                                }
1.1.1.6 ! root     2982:                                if ((opcode & 0x38) == 0x20) { // -(an)
1.1.1.4   root     2983:                                        incr = -1;
1.1.1.6 ! root     2984:                                        switch ((extra >> 11) & 3)
        !          2985:                                        {
        !          2986:                                                case 0: /* static pred */
        !          2987:                                                case 1: /* dynamic pred */
        !          2988:                                                regdir = -1;
        !          2989:                                                break;
        !          2990:                                        }
        !          2991:                                }
1.1       root     2992:                                if (extra & 0x2000) {
                   2993:                                        /* FMOVEM FPP->memory */
1.1.1.4   root     2994:                                        ad = fmovem2mem (ad, list, incr, regdir);
1.1       root     2995:                                } else {
                   2996:                                        /* FMOVEM memory->FPP */
1.1.1.4   root     2997:                                        ad = fmovem2fpp (ad, list, incr, regdir);
1.1       root     2998:                                }
1.1.1.6 ! root     2999:                                if ((opcode & 0x38) == 0x18 || (opcode & 0x38) == 0x20) // (an)+ or -(an)
1.1.1.4   root     3000:                                        m68k_areg (regs, opcode & 7) = ad;
1.1       root     3001:                        }
                   3002:                        return;
                   3003: 
                   3004:                case 0:
                   3005:                case 2: /* Extremely common */
1.1.1.6 ! root     3006:                        if (fp_exception_pending(true))
        !          3007:                                return;
        !          3008: 
1.1.1.4   root     3009:                        regs.fpiar = pc;
1.1       root     3010:                        reg = (extra >> 7) & 7;
                   3011:                        if ((extra & 0xfc00) == 0x5c00) {
1.1.1.6 ! root     3012:                                // FMOVECR
        !          3013:                                if (fault_if_unimplemented_680x0 (opcode, extra, ad, pc, &src, reg))
1.1.1.4   root     3014:                                        return;
1.1.1.6 ! root     3015:                                if (extra & 0x40) {
        !          3016:                                        // 6888x and ROM constant 0x40 - 0x7f: f-line
        !          3017:                                        fpu_noinst (opcode, pc);
1.1.1.4   root     3018:                                        return;
1.1       root     3019:                                }
1.1.1.6 ! root     3020:                                fpsr_clear_status();
        !          3021:                                fpu_get_constant(&regs.fp[reg], extra & 0x7f);
        !          3022:                                fpsr_make_status();
        !          3023:                                fpsr_check_arithmetic_exception(0, &src, opcode, extra, ad);
1.1       root     3024:                                return;
                   3025:                        }
1.1.1.4   root     3026: 
                   3027:                        // 6888x does not have special exceptions, check immediately
                   3028:                        if (fault_if_unimplemented_6888x (opcode, extra, pc))
                   3029:                                return;
                   3030: 
1.1.1.6 ! root     3031:                        fpsr_clear_status();
        !          3032: 
        !          3033:                        v = get_fp_value (opcode, extra, &src, pc, &ad);
1.1.1.4   root     3034:                        if (v <= 0) {
                   3035:                                if (v == 0)
                   3036:                                        fpu_noinst (opcode, pc);
1.1       root     3037:                                return;
                   3038:                        }
                   3039: 
1.1.1.6 ! root     3040:                        if (fault_if_no_fpu (opcode, extra, ad, pc))
1.1.1.4   root     3041:                                return;
1.1       root     3042: 
1.1.1.6 ! root     3043:                        dst = regs.fp[reg];
        !          3044: 
        !          3045:                        if (fp_is_dyadic(extra))
        !          3046:                                normalize_or_fault_if_no_denormal_support_dst(opcode, extra, ad, pc, &dst, &src);
        !          3047: 
        !          3048:                        // check for 680x0 unimplemented instruction
        !          3049:                        if (fault_if_unimplemented_680x0 (opcode, extra, ad, pc, &src, reg))
        !          3050:                                return;
        !          3051: 
        !          3052:                        // unimplemented datatype was checked in get_fp_value
        !          3053:                        if (regs.fp_unimp_pend) {
        !          3054:                                fp_exception_pending(false); // simplification: always mid/post-instruction exception
        !          3055:                                return;
        !          3056:                        }
        !          3057: 
        !          3058:                        v = fp_arithmetic(&src, &dst, extra);
        !          3059: 
        !          3060:                        fpsr_check_arithmetic_exception(0, &src, opcode, extra, ad);
        !          3061: 
        !          3062:                        if (v)
        !          3063:                                regs.fp[reg] = dst;
1.1       root     3064: 
                   3065:                        return;
                   3066:                default:
1.1.1.4   root     3067:                break;
                   3068:        }
                   3069:        fpu_noinst (opcode, pc);
                   3070: }
                   3071: 
                   3072: void fpuop_arithmetic (uae_u32 opcode, uae_u16 extra)
                   3073: {
                   3074:        regs.fpu_state = 1;
                   3075:        regs.fp_exception = false;
                   3076:        fpu_mmu_fixup = false;
                   3077:        fpuop_arithmetic2 (opcode, extra);
                   3078:        if (fpu_mmu_fixup) {
                   3079:                mmufixup[0].reg = -1;
                   3080:        }
1.1.1.6 ! root     3081: }
        !          3082: 
        !          3083: void fpu_modechange(void)
        !          3084: {
        !          3085:        uae_u32 temp_ext[8][3];
        !          3086:        int i;
        !          3087: 
        !          3088:        if (currprefs.fpu_softfloat == changed_prefs.fpu_softfloat)
        !          3089:                return;
        !          3090:        currprefs.fpu_softfloat = changed_prefs.fpu_softfloat;
        !          3091: 
        !          3092:        for (i = 0; i < 8; i++) {
        !          3093:                fpp_from_exten_fmovem(&regs.fp[i], &temp_ext[i][0], &temp_ext[i][1], &temp_ext[i][2]);
        !          3094:        }
1.1.1.4   root     3095:        if (currprefs.fpu_softfloat) {
1.1.1.6 ! root     3096:                fp_init_softfloat();
        !          3097:        } else {
        !          3098:                fp_init_native();
1.1       root     3099:        }
1.1.1.6 ! root     3100:        for (i = 0; i < 8; i++) {
        !          3101:                fpp_to_exten_fmovem(&regs.fp[i], temp_ext[i][0], temp_ext[i][1], temp_ext[i][2]);
        !          3102:        }
        !          3103: }
        !          3104: 
        !          3105: #if FPU_TEST
        !          3106: 
        !          3107: static void fpu_test(void)
        !          3108: {
        !          3109:        fpdata testp;
        !          3110:        uae_u32 packed[3];
        !          3111: 
        !          3112:        fpp_set_fpcr(0x30);
        !          3113:        fpp_to_exten_fmovem(&testp, 0xB4000000, 0x80000000, 0x000003fc);
        !          3114:        write_log(_T("INPUT: %s (%04x %16llx)\n"), fpp_print(&testp, -1), testp.fpx.high, testp.fpx.low);
        !          3115:        fpp_from_pack(&testp, packed, 17);
        !          3116:        fpp_to_pack(&testp, packed, 0);
1.1       root     3117: }
                   3118: 
1.1.1.6 ! root     3119: #endif
        !          3120: 
1.1       root     3121: void fpu_reset (void)
                   3122: {
1.1.1.6 ! root     3123:        if (currprefs.fpu_softfloat) {
        !          3124:                fp_init_softfloat();
        !          3125:        } else {
        !          3126:                fp_init_native();
        !          3127:        }
        !          3128: 
1.1.1.5   root     3129: #ifndef WINUAE_FOR_HATARI
                   3130: #if defined(CPU_i386) || defined(CPU_x86_64)
                   3131:        init_fpucw_x87();
                   3132: #endif
                   3133: #endif /* ! WINUAE_FOR_HATARI */
                   3134: 
1.1.1.6 ! root     3135:        regs.fpiar = 0;
1.1.1.4   root     3136:        regs.fpu_exp_state = 0;
1.1.1.6 ! root     3137:        fpp_set_fpcr (0);
        !          3138:        fpp_set_fpsr (0);
1.1       root     3139:        fpux_restore (NULL);
1.1.1.6 ! root     3140:        // reset precision
        !          3141:        fpp_set_mode(0x00000080 | 0x00000010);
        !          3142:        fpp_set_mode(0x00000000);
1.1.1.4   root     3143: 
1.1.1.6 ! root     3144: #if FPU_TEST
        !          3145:        fpu_test();
1.1.1.4   root     3146: #endif
1.1.1.6 ! root     3147: 
1.1       root     3148: }
                   3149: 
                   3150: uae_u8 *restore_fpu (uae_u8 *src)
                   3151: {
1.1.1.4   root     3152:        uae_u32 w1, w2, w3;
1.1       root     3153:        int i;
                   3154:        uae_u32 flags;
                   3155: 
1.1.1.5   root     3156:        fpu_reset();
1.1       root     3157:        changed_prefs.fpu_model = currprefs.fpu_model = restore_u32 ();
                   3158:        flags = restore_u32 ();
                   3159:        for (i = 0; i < 8; i++) {
1.1.1.4   root     3160:                w1 = restore_u16 () << 16;
                   3161:                w2 = restore_u32 ();
                   3162:                w3 = restore_u32 ();
1.1.1.6 ! root     3163:                fpp_to_exten_fmovem(&regs.fp[i], w1, w2, w3);
1.1       root     3164:        }
                   3165:        regs.fpcr = restore_u32 ();
                   3166:        regs.fpsr = restore_u32 ();
                   3167:        regs.fpiar = restore_u32 ();
1.1.1.6 ! root     3168:        fpsr_make_status();
1.1       root     3169:        if (flags & 0x80000000) {
1.1.1.4   root     3170:                restore_u32 ();
                   3171:                restore_u32 ();
1.1       root     3172:        }
1.1.1.6 ! root     3173:        if (flags & 0x20000000) {
        !          3174:                uae_u32 v = restore_u32();
        !          3175:                regs.fpu_state = (v >> 0) & 15;
        !          3176:                regs.fpu_exp_state = (v >> 4) & 15;
        !          3177:                regs.fp_unimp_pend = (v >> 8) & 15;
        !          3178:                regs.fp_exp_pend = (v >> 16) & 0xff;
        !          3179:                regs.fp_opword = restore_u16();
        !          3180:                regs.fp_ea = restore_u32();
        !          3181:                if (currprefs.fpu_model == 68060 || currprefs.fpu_model >= 68881) {
        !          3182:                        fsave_data.ccr = restore_u32();
        !          3183:                        fsave_data.eo[0] = restore_u32();
        !          3184:                        fsave_data.eo[1] = restore_u32();
        !          3185:                        fsave_data.eo[2] = restore_u32();
        !          3186:                }
        !          3187:                if (currprefs.fpu_model == 68060) {
        !          3188:                        fsave_data.v = restore_u32();
        !          3189:                }
        !          3190:                if (currprefs.fpu_model == 68040) {
        !          3191:                        fsave_data.fpiarcu = restore_u32();
        !          3192:                        fsave_data.cmdreg3b = restore_u32();
        !          3193:                        fsave_data.cmdreg1b = restore_u32();
        !          3194:                        fsave_data.stag = restore_u32();
        !          3195:                        fsave_data.dtag = restore_u32();
        !          3196:                        fsave_data.e1 = restore_u32();
        !          3197:                        fsave_data.e3 = restore_u32();
        !          3198:                        fsave_data.t = restore_u32();
        !          3199:                        fsave_data.fpt[0] = restore_u32();
        !          3200:                        fsave_data.fpt[1] = restore_u32();
        !          3201:                        fsave_data.fpt[2] = restore_u32();
        !          3202:                        fsave_data.et[0] = restore_u32();
        !          3203:                        fsave_data.et[1] = restore_u32();
        !          3204:                        fsave_data.et[2] = restore_u32();
        !          3205:                        fsave_data.wbt[0] = restore_u32();
        !          3206:                        fsave_data.wbt[1] = restore_u32();
        !          3207:                        fsave_data.wbt[2] = restore_u32();
        !          3208:                        fsave_data.grs = restore_u32();
        !          3209:                        fsave_data.wbte15 = restore_u32();
        !          3210:                        fsave_data.wbtm66 = restore_u32();
        !          3211:                }
        !          3212:        }
1.1.1.4   root     3213:        write_log(_T("FPU: %d\n"), currprefs.fpu_model);
1.1       root     3214:        return src;
                   3215: }
                   3216: 
                   3217: uae_u8 *save_fpu (int *len, uae_u8 *dstptr)
                   3218: {
1.1.1.6 ! root     3219:        uae_u32 w1, w2, w3, v;
1.1.1.4   root     3220:        uae_u8 *dstbak, *dst;
1.1       root     3221:        int i;
                   3222: 
                   3223:        *len = 0;
1.1.1.4   root     3224: #ifndef WINUAE_FOR_HATARI
1.1.1.6 ! root     3225:        /* Under Hatari, we save all FPU variables, even if fpu_model==0 */
1.1       root     3226:        if (currprefs.fpu_model == 0)
                   3227:                return 0;
1.1.1.4   root     3228: #endif
1.1       root     3229:        if (dstptr)
                   3230:                dstbak = dst = dstptr;
                   3231:        else
1.1.1.4   root     3232:                dstbak = dst = xmalloc (uae_u8, 4+4+8*10+4+4+4+4+4+2*10+3*(4+2));
1.1       root     3233:        save_u32 (currprefs.fpu_model);
1.1.1.6 ! root     3234:        save_u32 (0x80000000 | 0x20000000);
1.1       root     3235:        for (i = 0; i < 8; i++) {
1.1.1.6 ! root     3236:                fpp_from_exten_fmovem(&regs.fp[i], &w1, &w2, &w3);
1.1.1.4   root     3237:                save_u16 (w1 >> 16);
1.1       root     3238:                save_u32 (w2);
1.1.1.4   root     3239:                save_u32 (w3);
1.1       root     3240:        }
                   3241:        save_u32 (regs.fpcr);
                   3242:        save_u32 (regs.fpsr);
                   3243:        save_u32 (regs.fpiar);
1.1.1.4   root     3244: 
1.1       root     3245:        save_u32 (-1);
1.1.1.6 ! root     3246:        save_u32 (1);
1.1.1.4   root     3247: 
1.1.1.6 ! root     3248:        v = regs.fpu_state;
        !          3249:        v |= regs.fpu_exp_state << 4;
        !          3250:        v |= regs.fp_unimp_pend << 8;
        !          3251:        v |= regs.fp_exp_pend << 16;
        !          3252:        save_u32(v);
        !          3253:        save_u16(regs.fp_opword);
        !          3254:        save_u32(regs.fp_ea);
        !          3255: 
        !          3256:        if (currprefs.fpu_model == 68060 || currprefs.fpu_model >= 68881) {
        !          3257:                save_u32(fsave_data.ccr);
        !          3258:                save_u32(fsave_data.eo[0]);
        !          3259:                save_u32(fsave_data.eo[1]);
        !          3260:                save_u32(fsave_data.eo[2]);
        !          3261:        }
        !          3262:        if (currprefs.fpu_model == 68060) {
        !          3263:                save_u32(fsave_data.v);
        !          3264:        }
        !          3265:        if (currprefs.fpu_model == 68040) {
        !          3266:                save_u32(fsave_data.fpiarcu);
        !          3267:                save_u32(fsave_data.cmdreg3b);
        !          3268:                save_u32(fsave_data.cmdreg1b);
        !          3269:                save_u32(fsave_data.stag);
        !          3270:                save_u32(fsave_data.dtag);
        !          3271:                save_u32(fsave_data.e1);
        !          3272:                save_u32(fsave_data.e3);
        !          3273:                save_u32(fsave_data.t);
        !          3274:                save_u32(fsave_data.fpt[0]);
        !          3275:                save_u32(fsave_data.fpt[1]);
        !          3276:                save_u32(fsave_data.fpt[2]);
        !          3277:                save_u32(fsave_data.et[0]);
        !          3278:                save_u32(fsave_data.et[1]);
        !          3279:                save_u32(fsave_data.et[2]);
        !          3280:                save_u32(fsave_data.wbt[0]);
        !          3281:                save_u32(fsave_data.wbt[1]);
        !          3282:                save_u32(fsave_data.wbt[2]);
        !          3283:                save_u32(fsave_data.grs);
        !          3284:                save_u32(fsave_data.wbte15);
        !          3285:                save_u32(fsave_data.wbtm66);
        !          3286:        }
1.1.1.4   root     3287: 
1.1       root     3288:        *len = dst - dstbak;
                   3289:        return dstbak;
                   3290: }

unix.superglobalmegacorp.com

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