if (currprefs.cpu_model == 68060) {
// fsave data for 68060
reset_fsave_data();
+ regs.fpiar = oldpc;
} else if(currprefs.cpu_model == 68040) {
// fsave data for 68040
fsave_data.fpiarcu = regs.fpiar;
}
-static void fp_unimp_datatype(uae_u16 opcode, uae_u16 extra, uae_u32 ea, bool easet, uaecptr oldpc, fpdata *src, uae_u32 *packed)
+static void fp_unimp_datatype(uae_u16 opcode, uae_u16 extra, uae_u32 ea, bool easet, uaecptr oldpc, fpdata *src, uae_u32 *packed, bool predenormal)
{
uae_u32 reg = (extra >> 7) & 7;
uae_u32 size = (extra >> 10) & 7;
regs.fp_opword = opcode;
regs.fp_ea = ea;
regs.fp_ea_set = easet;
- regs.fp_unimp_pend = packed ? 2 : 1;
+ regs.fp_unimp_pend = packed ? 2 : (predenormal ? 3 : 1);
if((extra & 0x7f) == 4) // FSQRT 4->5
extra |= 1;
fsave_data.v = 7; // vector & 0x7
fpp_from_exten_fmovem(src, &fsave_data.eo[0], &fsave_data.eo[1], &fsave_data.eo[2]);
}
+ regs.fpiar = oldpc;
} else if (currprefs.cpu_model == 68040) {
// fsave data for 68040
fsave_data.cmdreg1b = extra;
regs.fp_unimp_ins = true;
regs.fp_ea = ea;
regs.fp_ea_set = easet;
+ regs.fpiar = oldpc;
fp_unimp_instruction_exception_pending();
return;
}
op_illg(opcode);
}
-static void fpu_unimpl(uae_u16 opcode, uaecptr pc)
-{
-#if EXCEPTION_FPP
- write_log(_T("Unknown FPU instruction %04X %08X\n"), opcode, pc);
-#endif
- regs.fp_exception = true;
- m68k_setpc(pc);
- Exception(55);
-}
-
static void fpu_noinst(uae_u16 opcode, uaecptr pc)
{
#if EXCEPTION_FPP
if (fault_if_no_fpu (opcode, extra, ea, easet, oldpc))
return true;
if (currprefs.cpu_model == 68060 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
- // 68060 FTRAP, FDBcc or FScc are not implemented.
+ // 68060 FTRAPcc, FDBcc and FScc are not implemented.
regs.fp_unimp_ins = true;
regs.fp_ea = ea;
regs.fp_ea_set = easet;
+ regs.fpiar = oldpc;
fp_unimp_instruction_exception_pending();
return true;
}
if (fpp_is_zero(src)) {
fpp_normalize(src); // 68040/060 can only fix unnormal zeros
} else {
- fp_unimp_datatype(opcode, extra, ea, easet, oldpc, src, NULL);
+ fp_unimp_datatype(opcode, extra, ea, easet, oldpc, src, NULL, true);
return true;
}
} else {
if (fpp_is_zero(dst)) {
fpp_normalize(dst); // 68040/060 can only fix unnormal zeros
} else {
- fp_unimp_datatype(opcode, extra, ea, easet, oldpc, src, NULL);
+ fp_unimp_datatype(opcode, extra, ea, easet, oldpc, src, NULL, false);
return true;
}
} else {
static bool fault_if_no_packed_support(uae_u16 opcode, uae_u16 extra, uaecptr ea, bool easet, uaecptr oldpc, fpdata *src, uae_u32 *packed)
{
if (currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
- fp_unimp_datatype(opcode, extra, ea, easet, oldpc, src, packed);
+ fp_unimp_datatype(opcode, extra, ea, easet, oldpc, src, packed, false);
return true;
}
return false;
int doext = 0;
if (!(extra & 0x4000)) {
+ // FPx to FPx
if (fault_if_no_fpu (opcode, extra, 0, false, oldpc))
return -1;
*src = regs.fp[(extra >> 10) & 7];
return -1;
switch (size)
{
- case 6:
+ case 6: // B
fpset(src, (uae_s8) m68k_dreg (regs, reg));
break;
- case 4:
+ case 4: // W
fpset(src, (uae_s16) m68k_dreg (regs, reg));
break;
- case 0:
+ case 0: // L
fpset(src, (uae_s32) m68k_dreg (regs, reg));
break;
- case 1:
+ case 1: // S
fpp_to_single (src, m68k_dreg (regs, reg));
normalize_or_fault_if_no_denormal_support(opcode, extra, 0, false, oldpc, src);
break;
- case 3: // packed
+ case 3: // P
if (currprefs.cpu_model == 68060) {
uae_u32 wrd[3];
if (fault_if_no_packed_support(opcode, extra, 0, false, oldpc, NULL, wrd))
}
return 0;
default:
+ if (currprefs.cpu_model >= 68040) {
+ if (fault_if_unimplemented_680x0(opcode, extra, ad, adset, oldpc, src, reg))
+ return -1;
+ regs.fpiar = oldpc;
+ }
return 0;
}
return 1;
case 1: // An
+ if (currprefs.cpu_model >= 68040) {
+ if (fault_if_unimplemented_680x0(opcode, extra, ad, adset, oldpc, src, reg))
+ return -1;
+ }
return 0;
case 2: // (An)
ad = m68k_areg (regs, reg);
if (fp_exception_pending(true))
return;
- regs.fpiar = pc;
reg = (extra >> 7) & 7;
if ((extra & 0xfc00) == 0x5c00) {
// FMOVECR
fpu_noinst (opcode, pc);
return;
}
+ regs.fpiar = pc;
fpsr_clear_status();
fpu_get_constant(®s.fp[reg], extra & 0x7f);
fpsr_make_status();
if (fault_if_no_fpu (opcode, extra, ad, adset, pc))
return;
+ regs.fpiar = pc;
dst = regs.fp[reg];
if (fp_is_dyadic(extra))
// unimplemented datatype was checked in get_fp_value
if (regs.fp_unimp_pend) {
- fp_exception_pending(false); // simplification: always mid/post-instruction exception
+ // simplification: always mid/post-instruction exception
+ fp_exception_pending(false);
return;
}
regs.fp[reg] = dst;
}
+ if (nonmaskable) {
+ fp_exception_pending(false);
+ }
+
return;
default:
break;