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)
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);
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);
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 (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));
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) {
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));
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:
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)
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)
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);
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);
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);
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;
}
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;
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;
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));
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:
switch ((extra >> 13) & 0x7)
{
case 3:
+ // FMOVE FPP->EA
if (fp_exception_pending(true))
return;
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) {
return;
}
} else if (extra & 0x2000) {
- /* FMOVEM FPP->memory */
+ /* FMOVEM Control Register->Memory */
uae_u32 ad;
int incr = 0;
}
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)
if ((opcode & 0x38) == 0x20)
m68k_areg (regs, opcode & 7) = ad;
} else {
- /* FMOVEM memory->FPP */
+ /* FMOVEM Memory->Control Register */
uae_u32 ad;
int incr = 0;
case 6:
case 7:
{
+ // FMOVEM FPP<>Memory
uae_u32 ad, list = 0;
int incr = 1;
int regdir = 1;
}
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 */
}
}
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)