]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
FMOVECR undefined offset values are now 100% identical to real 68881/68882. Statesave...
authorToni Wilen <twilen@winuae.net>
Tue, 8 Aug 2017 08:54:58 +0000 (11:54 +0300)
committerToni Wilen <twilen@winuae.net>
Tue, 8 Aug 2017 08:54:58 +0000 (11:54 +0300)
fpp.cpp

diff --git a/fpp.cpp b/fpp.cpp
index a8ded4e69b74bc65255aac21a966c8def1b14092..2048f77c1bf380e735dabe58af532453114757f7 100644 (file)
--- a/fpp.cpp
+++ b/fpp.cpp
@@ -185,24 +185,24 @@ static const struct fpp_cr_entry fpp_cr[22] = {
 #define FPP_CR_1E4096   21
 
 struct fpp_cr_entry_undef {
-       uae_u8 constant;
        uae_u32 val[3];
 };
 
+#define FPP_CR_NUM_SPECIAL_UNDEFINED 10
+
 // 68881 and 68882 have identical undefined fields
 static const struct fpp_cr_entry_undef fpp_cr_undef[] = {
-       { 0xff, {0x40000000, 0x00000000, 0x00000000} },
-       { 0x01, {0x40010000, 0xfe000682, 0x00000000} },
-       { 0x02, {0x40010000, 0xffc00503, 0x80000000} },
-       { 0x03, {0x20000000, 0x7fffffff, 0x00000000} },
-       { 0x04, {0x00000000, 0xffffffff, 0xffffffff} },
-       { 0x05, {0x3c000000, 0xffffffff, 0xfffff800} },
-       { 0x06, {0x3f800000, 0xffffff00, 0x00000000} },
-       { 0x07, {0x00010000, 0xf65d8d9c, 0x00000000} },
-       { 0x08, {0x7fff0000, 0x001e0000, 0x00000000} },
-       { 0x09, {0x43ff0000, 0x000e0000, 0x00000000} },
-       { 0x0a, {0x407f0000, 0x00060000, 0x00000000} },
-       { 0x00 }
+       { {0x40000000, 0x00000000, 0x00000000} },
+       { {0x40010000, 0xfe000682, 0x00000000} },
+       { {0x40010000, 0xffc00503, 0x80000000} },
+       { {0x20000000, 0x7fffffff, 0x00000000} },
+       { {0x00000000, 0xffffffff, 0xffffffff} },
+       { {0x3c000000, 0xffffffff, 0xfffff800} },
+       { {0x3f800000, 0xffffff00, 0x00000000} },
+       { {0x00010000, 0xf65d8d9c, 0x00000000} },
+       { {0x7fff0000, 0x001e0000, 0x00000000} },
+       { {0x43ff0000, 0x000e0000, 0x00000000} },
+       { {0x407f0000, 0x00060000, 0x00000000} }
 };
 
 uae_u32 xhex_nan[]   ={0x7fff0000, 0xffffffff, 0xffffffff};
@@ -631,7 +631,7 @@ static void fpsr_get_quotient(uae_u64 *quot, uae_u8 *sign)
 uae_u32 fpp_get_fpsr (void)
 {
 #ifdef JIT
-       if (currprefs.compfpu) {
+       if (currprefs.cachesize && currprefs.compfpu) {
                regs.fpsr &= 0x00fffff8; // clear cc
                if (fpp_is_nan (&regs.fp_result)) {
                        regs.fpsr |= FPSR_CC_NAN;
@@ -673,7 +673,7 @@ static void fpp_set_fpsr (uae_u32 val)
 
 #ifdef JIT
        // check comment in fpp_cond
-       if (currprefs.compfpu) {
+       if (currprefs.cachesize && currprefs.compfpu) {
                if (val & 0x01000000)
                        fpnan(&regs.fp_result);
                else if (val & 0x04000000)
@@ -688,9 +688,14 @@ static void fpp_set_fpsr (uae_u32 val)
 
 bool fpu_get_constant(fpdata *fpd, int cr)
 {
-       uae_u32 f[3] = { 0, 0, };
+       uae_u32 f[3] = { 0, 0, };
        int entry = -1;
        bool valid = true;
+       bool round = true;
+       int f1_adjust = 0;
+       uae_u32 sr = 0;
+       int mode = (regs.fpcr >> 4) & 3;
+       int prec = (regs.fpcr >> 6) & 3;
        
        switch (cr & 0x7f)
        {
@@ -762,20 +767,51 @@ bool fpu_get_constant(fpdata *fpd, int cr)
                        break;
                default: // undefined
                {
+                       bool check_f1_adjust = false;
                        const struct fpp_cr_entry_undef *fcr = fpp_cr_undef;
                        cr &= 0x7f;
-                       write_log (_T("Undocumented FPU constant access (index %02x)\n"), cr);
-                       // Most undefined fields contain this
-                       f[0] = fcr[0].val[0];
-                       f[1] = fcr[0].val[1];
-                       f[2] = fcr[0].val[2];
-                       // Other undefined fields
-                       for (int i = 1; fcr[i].constant; i++) {
-                               if (fcr[i].constant == cr) {
-                                       f[0] = fcr[i].val[0];
-                                       f[1] = fcr[i].val[1];
-                                       f[2] = fcr[i].val[2];
-                                       break;
+                       if (cr > FPP_CR_NUM_SPECIAL_UNDEFINED) {
+                               // Most undefined fields contain this
+                               cr = 0;
+                               // Do not round or normalize
+                               round = false;
+                               // Zero
+                               sr |= FPSR_CC_Z;
+                       }
+                       f[0] = fcr[cr].val[0];
+                       f[1] = fcr[cr].val[1];
+                       f[2] = fcr[cr].val[2];
+                       // Rounding mode and precision works very strangely here..
+                       switch (cr)
+                       {
+                               case 1:
+                               check_f1_adjust = true;
+                               break;
+                               case 2:
+                               if (prec == 1 && mode == 3)
+                                       f1_adjust = -1;
+                               break;
+                               case 3:
+                               if (prec == 1 && (mode == 0 || mode == 3))
+                                       sr |= FPSR_CC_I;
+                               else
+                                       sr |= FPSR_CC_NAN;
+                               break;
+                               case 7:
+                               sr |= FPSR_CC_NAN;
+                               check_f1_adjust = true;
+                               break;
+                               case 8:
+                               round = false;
+                               break;
+                       }
+                       if (check_f1_adjust) {
+                               if (prec == 1) {
+                                       if (mode == 0) {
+                                               f1_adjust = -1;
+                                       } else if (mode == 1 || mode == 2) {
+                                               f1_adjust = 1;
+                                       }
                                }
                        }
                        valid = false;
@@ -791,18 +827,27 @@ bool fpu_get_constant(fpdata *fpd, int cr)
                // note: with valid constants, LSB never wraps
                if (fpp_cr[entry].inexact) {
                        fpsr_set_exception(FPSR_INEX2);
-                       f[2] += fpp_cr[entry].rndoff[(regs.fpcr >> 4) & 3];
+                       f[2] += fpp_cr[entry].rndoff[mode];
                }
        }
 
        fpp_to_exten_fmovem(fpd, f[0], f[1], f[2]);
        
-       if (((regs.fpcr >> 6) & 3) == 1)
-               fpp_round32(fpd);
-       if (((regs.fpcr >> 6) & 3) >= 2)
-               fpp_round64(fpd);
+       if (round) {
+               if (((regs.fpcr >> 6) & 3) == 1)
+                       fpp_round32(fpd);
+               if (((regs.fpcr >> 6) & 3) >= 2)
+                       fpp_round64(fpd);
+       }
        
+       if (f1_adjust) {
+               fpp_from_exten_fmovem(fpd, &f[0], &f[1], &f[2]);
+               f[1] += f1_adjust * 0x80;
+               fpp_to_exten_fmovem(fpd, f[0], f[1], f[2]);
+       }
+
        fpsr_set_result(fpd);
+       regs.fpsr |= sr;
 
        return valid;
 }
@@ -1690,7 +1735,7 @@ int fpp_cond (int condition)
        int NotANumber, N, Z;
 
 #ifdef JIT
-       if (currprefs.compfpu) {
+       if (currprefs.cachesize && currprefs.compfpu) {
                // JIT reads and writes regs.fpu_result
                NotANumber = fpp_is_nan(&regs.fp_result);
                N = fpp_is_neg(&regs.fp_result);
@@ -3102,33 +3147,53 @@ uae_u8 *restore_fpu (uae_u8 *src)
                restore_u32 ();
                restore_u32 ();
        }
-       if (flags & 0x40000000) {
-               w1 = restore_u16() << 16;
-               w2 = restore_u32();
-               w3 = restore_u32();
-               //fpp_to_exten_fmovem(&fsave_data.src, w1, w2, w3);
-               w1 = restore_u16() << 16;
-               w2 = restore_u32();
-               w3 = restore_u32();
-               //fpp_to_exten_fmovem(&fsave_data.dst, w1, w2, w3);
-               restore_u32(); // fsave_data.pack[0] = restore_u32();
-               restore_u32(); // fsave_data.pack[1] = restore_u32();
-               restore_u32(); // fsave_data.pack[2] = restore_u32();
-               restore_u16(); // fsave_data.opcode = restore_u16();
-               restore_u16(); // fsave_data.extra = restore_u16();
-               restore_u16(); //fsave_data.type = restore_u16();
-       }
-       regs.fpu_state = (flags & 1) ? 0 : 1;
-       regs.fpu_exp_state = (flags & 2) ? 1 : 0;
-       if (flags & 4)
-               regs.fpu_exp_state = 2;
+       if (flags & 0x20000000) {
+               uae_u32 v = restore_u32();
+               regs.fpu_state = (v >> 0) & 15;
+               regs.fpu_exp_state = (v >> 4) & 15;
+               regs.fp_unimp_pend = (v >> 8) & 15;
+               regs.fp_exp_pend = (v >> 16) & 0xff;
+               regs.fp_opword = restore_u16();
+               regs.fp_ea = restore_u32();
+               if (currprefs.fpu_model == 68060 || currprefs.fpu_model >= 68881) {
+                       fsave_data.ccr = restore_u32();
+                       fsave_data.eo[0] = restore_u32();
+                       fsave_data.eo[1] = restore_u32();
+                       fsave_data.eo[2] = restore_u32();
+               }
+               if (currprefs.fpu_model == 68060) {
+                       fsave_data.v = restore_u32();
+               }
+               if (currprefs.fpu_model == 68040) {
+                       fsave_data.fpiarcu = restore_u32();
+                       fsave_data.cmdreg3b = restore_u32();
+                       fsave_data.cmdreg1b = restore_u32();
+                       fsave_data.stag = restore_u32();
+                       fsave_data.dtag = restore_u32();
+                       fsave_data.e1 = restore_u32();
+                       fsave_data.e3 = restore_u32();
+                       fsave_data.t = restore_u32();
+                       fsave_data.fpt[0] = restore_u32();
+                       fsave_data.fpt[1] = restore_u32();
+                       fsave_data.fpt[2] = restore_u32();
+                       fsave_data.et[0] = restore_u32();
+                       fsave_data.et[1] = restore_u32();
+                       fsave_data.et[2] = restore_u32();
+                       fsave_data.wbt[0] = restore_u32();
+                       fsave_data.wbt[1] = restore_u32();
+                       fsave_data.wbt[2] = restore_u32();
+                       fsave_data.grs = restore_u32();
+                       fsave_data.wbte15 = restore_u32();
+                       fsave_data.wbtm66 = restore_u32();
+               }
+       }
        write_log(_T("FPU: %d\n"), currprefs.fpu_model);
        return src;
 }
 
 uae_u8 *save_fpu (int *len, uae_u8 *dstptr)
 {
-       uae_u32 w1, w2, w3;
+       uae_u32 w1, w2, w3, v;
        uae_u8 *dstbak, *dst;
        int i;
 
@@ -3140,7 +3205,7 @@ uae_u8 *save_fpu (int *len, uae_u8 *dstptr)
        else
                dstbak = dst = xmalloc (uae_u8, 4+4+8*10+4+4+4+4+4+2*10+3*(4+2));
        save_u32 (currprefs.fpu_model);
-       save_u32 (0x80000000 | 0x40000000 | (regs.fpu_state == 0 ? 1 : 0) | (regs.fpu_exp_state ? 2 : 0) | (regs.fpu_exp_state > 1 ? 4 : 0));
+       save_u32 (0x80000000 | 0x20000000);
        for (i = 0; i < 8; i++) {
                fpp_from_exten_fmovem(&regs.fp[i], &w1, &w2, &w3);
                save_u16 (w1 >> 16);
@@ -3152,26 +3217,48 @@ uae_u8 *save_fpu (int *len, uae_u8 *dstptr)
        save_u32 (regs.fpiar);
 
        save_u32 (-1);
-       save_u32 (0);
-
-       w1 = w2 = w3 = 0;
-       //fpp_from_exten_fmovem(&fsave_data.src, &w1, &w2, &w3);
-       save_u16(w1 >> 16);
-       save_u32(w2);
-       save_u32(w3);
-       //fpp_from_exten_fmovem(&fsave_data.dst, &w1, &w2, &w3);
-       save_u16(w1 >> 16);
-       save_u32(w2);
-       save_u32(w3);
-       save_u32(0); // save_u32(fsave_data.pack[0]);
-       save_u32(0); // save_u32(fsave_data.pack[1]);
-       save_u32(0); // save_u32(fsave_data.pack[2]);
-       save_u16(0); // save_u16(fsave_data.opcode);
-       save_u16(0); // save_u16(fsave_data.extra);
-       save_u16(0); //fsave_data.exp_type);
+       save_u32 (1);
+
+       v = regs.fpu_state;
+       v |= regs.fpu_exp_state << 4;
+       v |= regs.fp_unimp_pend << 8;
+       v |= regs.fp_exp_pend << 16;
+       save_u32(v);
+       save_u16(regs.fp_opword);
+       save_u32(regs.fp_ea);
+
+       if (currprefs.fpu_model == 68060 || currprefs.fpu_model >= 68881) {
+               save_u32(fsave_data.ccr);
+               save_u32(fsave_data.eo[0]);
+               save_u32(fsave_data.eo[1]);
+               save_u32(fsave_data.eo[2]);
+       }
+       if (currprefs.fpu_model == 68060) {
+               save_u32(fsave_data.v);
+       }
+       if (currprefs.fpu_model == 68040) {
+               save_u32(fsave_data.fpiarcu);
+               save_u32(fsave_data.cmdreg3b);
+               save_u32(fsave_data.cmdreg1b);
+               save_u32(fsave_data.stag);
+               save_u32(fsave_data.dtag);
+               save_u32(fsave_data.e1);
+               save_u32(fsave_data.e3);
+               save_u32(fsave_data.t);
+               save_u32(fsave_data.fpt[0]);
+               save_u32(fsave_data.fpt[1]);
+               save_u32(fsave_data.fpt[2]);
+               save_u32(fsave_data.et[0]);
+               save_u32(fsave_data.et[1]);
+               save_u32(fsave_data.et[2]);
+               save_u32(fsave_data.wbt[0]);
+               save_u32(fsave_data.wbt[1]);
+               save_u32(fsave_data.wbt[2]);
+               save_u32(fsave_data.grs);
+               save_u32(fsave_data.wbte15);
+               save_u32(fsave_data.wbtm66);
+       }
 
        *len = dst - dstbak;
        return dstbak;
 }
-
-