From: Toni Wilen Date: Fri, 8 Jun 2018 20:05:14 +0000 (+0300) Subject: Add missing invalid addressing mode checks for FMOVEM, FMOVE(M) Control Register... X-Git-Tag: 4000~26 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=9b75979c8912e85624459fef97be98c7eba863ab;p=francis%2Fwinuae.git Add missing invalid addressing mode checks for FMOVEM, FMOVE(M) Control Register, FMOVE FPP,EA. Add more comments. --- diff --git a/fpp.cpp b/fpp.cpp index 2150a5e4..c9502763 100644 --- a/fpp.cpp +++ b/fpp.cpp @@ -1326,7 +1326,7 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old size = (extra >> 10) & 7; switch (mode) { - case 0: + case 0: // Dn if ((size == 0 || size == 1 ||size == 4 || size == 6) && fault_if_no_fpu (opcode, extra, 0, oldpc)) return -1; switch (size) @@ -1348,12 +1348,12 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old return 0; } return 1; - case 1: + case 1: // An return 0; - case 2: + case 2: // (An) ad = m68k_areg (regs, reg); break; - case 3: + case 3: // (An)+ // Also needed by fault_if_no_fpu mmufixup[0].reg = reg; mmufixup[0].value = m68k_areg (regs, reg); @@ -1361,7 +1361,7 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old ad = m68k_areg (regs, reg); m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; break; - case 4: + case 4: // -(An) // Also needed by fault_if_no_fpu mmufixup[0].reg = reg; mmufixup[0].value = m68k_areg (regs, reg); @@ -1372,10 +1372,10 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old if (currprefs.cpu_model == 68060 && if_no_fpu() && sz1[size] == 12) ad += 8; break; - case 5: + case 5: // (d16,An) ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_cp_next_iword (); break; - case 6: + case 6: // (d8,An,Xn)+ ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg), 0); break; case 7: @@ -1444,14 +1444,14 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old switch (size) { - case 0: + case 0: // L fpset(src, (uae_s32) (doext ? exts[0] : x_cp_get_long (ad))); break; - case 1: + case 1: // S fpp_to_single (src, (doext ? exts[0] : x_cp_get_long (ad))); normalize_or_fault_if_no_denormal_support(opcode, extra, adold, oldpc, src); break; - case 2: + case 2: // X { uae_u32 wrd1, wrd2, wrd3; wrd1 = (doext ? exts[0] : x_cp_get_long (ad)); @@ -1463,7 +1463,7 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old normalize_or_fault_if_no_denormal_support(opcode, extra, adold, oldpc, src); } break; - case 3: + case 3: // P { uae_u32 wrd[3]; if (currprefs.cpu_model == 68060) { @@ -1482,10 +1482,10 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old return 1; } break; - case 4: + case 4: // W fpset(src, (uae_s16) (doext ? exts[0] : x_cp_get_word (ad))); break; - case 5: + case 5: // D { uae_u32 wrd1, wrd2; wrd1 = (doext ? exts[0] : x_cp_get_long (ad)); @@ -1495,7 +1495,7 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old normalize_or_fault_if_no_denormal_support(opcode, extra, adold, oldpc, src); } break; - case 6: + case 6: // B fpset(src, (uae_s8) (doext ? exts[0] : x_cp_get_byte (ad))); break; default: @@ -1528,13 +1528,13 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o size = (extra >> 10) & 7; switch (mode) { - case 0: + case 0: // Dn if ((size == 0 || size == 1 ||size == 4 || size == 6) && fault_if_no_fpu (opcode, extra, 0, oldpc)) return -1; switch (size) { - case 6: + case 6: // B if (normalize_or_fault_if_no_denormal_support(opcode, extra, 0, oldpc, value)) return 1; m68k_dreg (regs, reg) = (uae_u32)(((fpp_to_int (value, 0) & 0xff) @@ -1542,7 +1542,7 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o if (fault_if_68040_integer_nonmaskable(opcode, extra, ad, oldpc, value)) return -1; break; - case 4: + case 4: // W if (normalize_or_fault_if_no_denormal_support(opcode, extra, 0, oldpc, value)) return 1; m68k_dreg (regs, reg) = (uae_u32)(((fpp_to_int (value, 1) & 0xffff) @@ -1550,14 +1550,14 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o if (fault_if_68040_integer_nonmaskable(opcode, extra, ad, oldpc, value)) return -1; break; - case 0: + case 0: // L if (normalize_or_fault_if_no_denormal_support(opcode, extra, 0, oldpc, value)) return 1; m68k_dreg (regs, reg) = (uae_u32)fpp_to_int (value, 2); if (fault_if_68040_integer_nonmaskable(opcode, extra, ad, oldpc, value)) return -1; break; - case 1: + case 1: // S if (normalize_or_fault_if_no_denormal_support(opcode, extra, 0, oldpc, value)) return 1; m68k_dreg (regs, reg) = fpp_from_single (value); @@ -1566,12 +1566,12 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o return 0; } return 1; - case 1: + case 1: // An return 0; - case 2: + case 2: // (An) ad = m68k_areg (regs, reg); break; - case 3: + case 3: // (An)+ // Also needed by fault_if_no_fpu mmufixup[0].reg = reg; mmufixup[0].value = m68k_areg (regs, reg); @@ -1579,7 +1579,7 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o ad = m68k_areg (regs, reg); m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; break; - case 4: + case 4: // -(An) // Also needed by fault_if_no_fpu mmufixup[0].reg = reg; mmufixup[0].value = m68k_areg (regs, reg); @@ -1590,28 +1590,22 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o if (currprefs.cpu_model == 68060 && if_no_fpu() && sz1[size] == 12) ad += 8; break; - case 5: + case 5: // (d16,An) ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_cp_next_iword (); break; - case 6: + case 6: // (d8,An,Xn)+ ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg), 0); break; case 7: switch (reg) { - case 0: + case 0: // (xxx).W ad = (uae_s32) (uae_s16) x_cp_next_iword (); break; - case 1: + case 1: // (xxx).L ad = x_cp_next_ilong (); break; - case 2: - ad = m68k_getpc (); - ad += (uae_s32) (uae_s16) x_cp_next_iword (); - break; - case 3: - ad = x_cp_get_disp_ea_020 (m68k_getpc (), 0); - break; + // Immediate and PC-relative modes are not supported default: return 0; } @@ -1624,19 +1618,19 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o switch (size) { - case 0: + case 0: // L if (normalize_or_fault_if_no_denormal_support(opcode, extra, ad, oldpc, value)) return 1; x_cp_put_long(ad, (uae_u32)fpp_to_int(value, 2)); if (fault_if_68040_integer_nonmaskable(opcode, extra, ad, oldpc, value)) return -1; break; - case 1: + case 1: // S if (normalize_or_fault_if_no_denormal_support(opcode, extra, ad, oldpc, value)) return 1; x_cp_put_long(ad, fpp_from_single(value)); break; - case 2: + case 2: // X { if (normalize_or_fault_if_no_denormal_support(opcode, extra, ad, oldpc, value)) return 1; @@ -1669,14 +1663,14 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o x_cp_put_long (ad, wrd[2]); } break; - case 4: + case 4: // W if (normalize_or_fault_if_no_denormal_support(opcode, extra, ad, oldpc, value)) return 1; x_cp_put_word(ad, (uae_s16)fpp_to_int(value, 1)); if (fault_if_68040_integer_nonmaskable(opcode, extra, ad, oldpc, value)) return -1; break; - case 5: + case 5: // D { if (normalize_or_fault_if_no_denormal_support(opcode, extra, ad, oldpc, value)) return 1; @@ -1687,7 +1681,7 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o x_cp_put_long (ad, wrd2); } break; - case 6: + case 6: // B if (normalize_or_fault_if_no_denormal_support(opcode, extra, ad, oldpc, value)) return 1; x_cp_put_byte(ad, (uae_s8)fpp_to_int(value, 0)); @@ -1709,38 +1703,38 @@ static int get_fp_ad (uae_u32 opcode, uae_u32 * ad) reg = opcode & 7; switch (mode) { - case 0: - case 1: + case 0: // Dn + case 1: // An return 0; - case 2: + case 2: // (An) *ad = m68k_areg (regs, reg); break; - case 3: + case 3: // (An)+ *ad = m68k_areg (regs, reg); break; - case 4: + case 4: // -(An) *ad = m68k_areg (regs, reg); break; - case 5: + case 5: // (d16,An) *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_cp_next_iword (); break; - case 6: + case 6: // (d8,An,Xn)+ *ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg), 0); break; case 7: switch (reg) { - case 0: + case 0: // (xxx).W *ad = (uae_s32) (uae_s16) x_cp_next_iword (); break; - case 1: + case 1: // (xxx).L *ad = x_cp_next_ilong (); break; - case 2: + case 2: // (d16,PC) *ad = m68k_getpc (); *ad += (uae_s32) (uae_s16) x_cp_next_iword (); break; - case 3: + case 3: // (d8,PC,Xn)+ *ad = x_cp_get_disp_ea_020 (m68k_getpc (), 0); break; default: @@ -2806,6 +2800,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) switch ((extra >> 13) & 0x7) { case 3: + // FMOVE FPP->EA if (fp_exception_pending(true)) return; @@ -2825,41 +2820,52 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) case 4: case 5: + // FMOVE Control Register <> Data or Address register if ((opcode & 0x38) == 0) { + // Dn if (fault_if_no_fpu (opcode, extra, 0, pc)) return; + // Only single selected control register is allowed + // All control register bits unset = FPIAR + uae_u16 bits = extra & (0x1000 | 0x0800 | 0x0400); + if (bits && bits != 0x1000 && bits != 0x0800 && bits != 0x400) { + // 68060 does not generate f-line if multiple bits are set + // but it also works unexpectedly, just do nothing for now. + if (currprefs.fpu_model != 68060) + fpu_noinst(opcode, pc); + return; + } if (extra & 0x2000) { if (extra & 0x1000) m68k_dreg (regs, opcode & 7) = fpp_get_fpcr(); if (extra & 0x0800) m68k_dreg (regs, opcode & 7) = fpp_get_fpsr(); - if (extra & 0x0400) + if ((extra & 0x0400) || !bits) m68k_dreg (regs, opcode & 7) = regs.fpiar; } else { if (extra & 0x1000) fpp_set_fpcr(m68k_dreg (regs, opcode & 7)); if (extra & 0x0800) fpp_set_fpsr(m68k_dreg (regs, opcode & 7)); - if (extra & 0x0400) + if ((extra & 0x0400) || !bits) regs.fpiar = m68k_dreg (regs, opcode & 7); } } else if ((opcode & 0x38) == 0x08) { + // An if (fault_if_no_fpu (opcode, extra, 0, pc)) return; + // Only FPIAR can be moved to/from address register + // All bits unset = FPIAR + uae_u16 bits = extra & (0x1000 | 0x0800 | 0x0400); + // 68060, An and all bits unset: f-line + if ((bits && bits != 0x0400) || (!bits && currprefs.fpu_model == 68060)) { + fpu_noinst(opcode, pc); + return; + } if (extra & 0x2000) { - if (extra & 0x1000) - m68k_areg (regs, opcode & 7) = fpp_get_fpcr(); - if (extra & 0x0800) - m68k_areg (regs, opcode & 7) = fpp_get_fpsr(); - if (extra & 0x0400) - m68k_areg (regs, opcode & 7) = regs.fpiar; + m68k_areg (regs, opcode & 7) = regs.fpiar; } else { - if (extra & 0x1000) - fpp_set_fpcr(m68k_areg (regs, opcode & 7)); - if (extra & 0x0800) - fpp_set_fpsr(m68k_areg (regs, opcode & 7)); - if (extra & 0x0400) - regs.fpiar = m68k_areg (regs, opcode & 7); + regs.fpiar = m68k_areg (regs, opcode & 7); } } else if ((opcode & 0x3f) == 0x3c) { if ((extra & 0x2000) == 0) { @@ -2892,7 +2898,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) return; } } else if (extra & 0x2000) { - /* FMOVEM FPP->memory */ + /* FMOVEM Control Register->Memory */ uae_u32 ad; int incr = 0; @@ -2902,6 +2908,11 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) } if (fault_if_no_fpu (opcode, extra, ad, pc)) return; + if ((opcode & 0x3f) >= 0x3a) { + // PC relative modes not supported + fpu_noinst(opcode, pc); + return; + } if ((opcode & 0x38) == 0x20) { if (extra & 0x1000) @@ -2930,7 +2941,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) if ((opcode & 0x38) == 0x20) m68k_areg (regs, opcode & 7) = ad; } else { - /* FMOVEM memory->FPP */ + /* FMOVEM Memory->Control Register */ uae_u32 ad; int incr = 0; @@ -2972,6 +2983,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) case 6: case 7: { + // FMOVEM FPP<>Memory uae_u32 ad, list = 0; int incr = 1; int regdir = 1; @@ -2981,6 +2993,18 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) } if (fault_if_no_fpu (opcode, extra, ad, pc)) return; + + if ((extra & 0x2000) && ((opcode & 0x38) == 0x18 || (opcode & 0x3f) >= 0x3a)) { + // FMOVEM FPP->Memory: (An)+ and PC relative modes not supported + fpu_noinst(opcode, pc); + return; + } + if (!(extra & 0x2000) && (opcode & 0x38) == 0x20) { + // FMOVEM Memory->FPP: -(An) not supported + fpu_noinst(opcode, pc); + return; + } + switch ((extra >> 11) & 3) { case 0: /* static pred */ @@ -3005,10 +3029,10 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) } } if (extra & 0x2000) { - /* FMOVEM FPP->memory */ + /* FMOVEM FPP->Memory */ ad = fmovem2mem (ad, list, incr, regdir); } else { - /* FMOVEM memory->FPP */ + /* FMOVEM Memory->FPP */ ad = fmovem2fpp (ad, list, incr, regdir); } if ((opcode & 0x38) == 0x18 || (opcode & 0x38) == 0x20) // (an)+ or -(an)