#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};
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 (®s.fp_result)) {
regs.fpsr |= FPSR_CC_NAN;
#ifdef JIT
// check comment in fpp_cond
- if (currprefs.compfpu) {
+ if (currprefs.cachesize && currprefs.compfpu) {
if (val & 0x01000000)
fpnan(®s.fp_result);
else if (val & 0x04000000)
bool fpu_get_constant(fpdata *fpd, int cr)
{
- uae_u32 f[3] = { 0, 0, };
+ uae_u32 f[3] = { 0, 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)
{
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;
// 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;
}
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(®s.fp_result);
N = fpp_is_neg(®s.fp_result);
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;
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(®s.fp[i], &w1, &w2, &w3);
save_u16 (w1 >> 16);
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;
}
-
-