Re: [hatari-devel] Basic cpu testsuite |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/hatari-devel Archives
]
On 8.6.2018 22.00, Toni Wilen wrote:
>> Good catch. It also lacks check if multiple control register bits are
>> set at the same time (or none) which works strangely on 68060.. I'll
>> attach patch later today.
>
> Patch attached.
>
> - FMOVE control register<>Dn/An missing validation added.
> - FMOVEM fpp<>ea missing -(an)/(an)+ validation added. (Oddly enough
> control register FMOVEM do not have same addressing mode restrictions)
Some more changes: PC relative addressing modes was incorrectly allowed
when writing to memory. Added some comments.
diff --git "a/C:\\Users\\TONI~1.WIL\\AppData\\Local\\Temp\\TortoiseGit\\fpp-fc4d3c3.003.cpp" "b/C:\\projects\\winuae\\src\\fpp.cpp"
index 2150a5e4..c9502763 100644
--- "a/C:\\Users\\TONI~1.WIL\\AppData\\Local\\Temp\\TortoiseGit\\fpp-fc4d3c3.003.cpp"
+++ "b/C:\\projects\\winuae\\src\\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)