// first check for pending arithmetic exceptions
if (currprefs.fpu_exceptions) {
if (regs.fp_exp_pend) {
+ write_log (_T("FPU ARITHMETIC EXCEPTION (%d)\n"), regs.fp_exp_pend);
regs.fpu_exp_pre = pre;
Exception(regs.fp_exp_pend);
if (currprefs.fpu_model != 68882)
bool exp_e3 = false;
// fsave data for 68040
+ fsave_data.fpiarcu = regs.fpiar;
+
if (opclass == 3) { // OPCLASS 011
fsave_data.cmdreg1b = extra;
fsave_data.e1 = 1;
return valid;
}
+#if 0
static void fpu_format_error (void)
{
uaecptr newpc;
#endif
regs.fp_exception = true;
}
+#endif
static void fpu_op_unimp_instruction(uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr oldpc, fpdata *src, int reg, int size)
{
fpp_get_exceptional_operand(&fsave_data.eo[0], &fsave_data.eo[1], &fsave_data.eo[2]);
} else if(currprefs.cpu_model == 68040) {
// fsave data for 68040
- if (regs.fp_unimp_pend & 2) {
- // packed data has been saved by fp_check_unimp_datatype
- } else {
+ fsave_data.fpiarcu = regs.fpiar;
+
+ if (!regs.fp_unimp_pend) { // else data has been saved by fp_check_unimp_datatype
reset_fsave_data();
fsave_data.cmdreg3b = (extra & 0x3C3) | ((extra & 0x038) >> 1) | ((extra & 0x004) << 3);
fsave_data.cmdreg1b = extra;
} else if (currprefs.cpu_model == 68040) {
// fsave data for 68040
fsave_data.cmdreg1b = extra;
+ fsave_data.fpiarcu = regs.fpiar;
if (packed) {
fsave_data.e1 = 1; // used to distinguish packed operands
}
if (opclass == 3) { // OPCLASS 011
fsave_data.t = 1;
fpp_from_exten_fmovem(src, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]);
- fsave_data.stag = get_ftag(src, size);
- if(reg >= 0) {
- fpp_from_exten_fmovem(®s.fp[reg], &fsave_data.fpt[0], &fsave_data.fpt[1], &fsave_data.fpt[2]);
- fsave_data.dtag = get_ftag(®s.fp[reg], -1);
- }
+ fsave_data.stag = get_ftag(src, -1);
+ fpp_from_exten_fmovem(src, &fsave_data.fpt[0], &fsave_data.fpt[1], &fsave_data.fpt[2]); // undocumented
+ fsave_data.dtag = get_ftag(src, -1); // undocumented
} else { // OPCLASS 000 and 010
if (packed) {
fsave_data.fpt[2] = packed[0]; // yes, this is correct.
fsave_data.stag = 7; // undocumented
} else {
fpp_from_exten_fmovem(src, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]);
- fsave_data.stag = get_ftag(src, size);
+ fsave_data.stag = get_ftag(src, (opclass == 0) ? -1 : size);
+ if (fsave_data.stag == 5) {
+ fsave_data.et[0] = (size == 1) ? 0x3f800000 : 0x3c000000; // exponent for denormalized single and double
+ }
if (dyadic) {
fpp_from_exten_fmovem(®s.fp[reg], &fsave_data.fpt[0], &fsave_data.fpt[1], &fsave_data.fpt[2]);
fsave_data.dtag = get_ftag(®s.fp[reg], -1);
ad += 4;
x_put_long(ad, 0);
ad += 4;
- x_put_long(ad, regs.fpiar); // FPIARCU (same as FPU PC or something else?)
+ x_put_long(ad, fsave_data.fpiarcu); // FPIARCU (same as FPU PC or something else?)
ad += 4;
x_put_long(ad, 0);
ad += 4;
} else if (currprefs.fpu_model == 68040) {
- int ff = (d >> 8) & 0xff;
+ if ((d & 0xff000000) != 0) { // not null frame
+ uae_u32 frame_size = (d >> 16) & 0xff;
- if (ff == 0x00) { // null
- fpu_null();
- } else if (ff == 0x60 || ff == 0x30) { // busy or idle
- // TODO: restore frame contents
- if (incr < 0) {
- ad -= ff;
- } else {
- ad += ff;
+ if (frame_size == 0x60 || (frame_size == 0x30 || frame_size == 0x28)) { // busy or unimp
+ // TODO: restore frame contents
+ if (incr < 0) {
+ ad -= frame_size;
+ } else {
+ ad += frame_size;
+ }
+ } else if (frame_size != 0x00) { // not idle
+ write_log (_T("FRESTORE invalid frame format %02X!\n"), frame_size);
}
- } else {
- write_log (_T("FRESTORE invalid frame format %02X!\n"), ff);
+ } else { // null frame
+ fpu_null();
}
} else {