Re: [hatari-devel] 68000: Wrong order of bus accesses for move.l xx,-(Ay) |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/hatari-devel Archives
]
>> If so, I guess Toni will be able to reproduce this on Amiga and update
>> the cpu core accordingly.
>
> I'll confirm (and fix) this tomorrow but I am quite sure it is wrong
> because 68000 generally does long -(an) writes in descending order.
>
> I may have missed this or broken it later because I carefully tested
> each variant years ago.
This should fix it. Also fixes exception stack frame fault address if
MOVE.L ea,-(an) causes address error.
There is still possible bug if write causes bus error, An register may
be wrong (It should be only decreased by 2 if first word write causes
bus error). I can't test this easily but address and bus error behavior
should be same in this situation. Most likely no one cares but it still
should be emulated accurately.
gencpu.cpp | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/gencpu.cpp b/gencpu.cpp
index 200da47..bbb9422 100644
--- a/gencpu.cpp
+++ b/gencpu.cpp
@@ -64,6 +64,7 @@ static int optimized_flags;
#define GF_NOFAULTPC 512
#define GF_RMW 1024
#define GF_OPCE020 2048
+#define GF_REVERSE 4096
/* For the current opcode, the next lower level that will have
different code.
* Initialized to -1 for each opcode. If it remains unchanged, indicates we
@@ -1631,6 +1632,9 @@ static void genamode2x (amodes mode, const char
*reg, wordsizes size, const char
printf ("\tif (%sa & 1) {\n", name);
if (exception_pc_offset)
incpc("%d", exception_pc_offset);
+ // MOVE.L EA,-(An) causing address error: stacked value is original
An - 2, not An - 4.
+ if ((flags & GF_REVERSE) && size == sz_long)
+ printf("\t\t%sa += 2;\n", name);
printf ("\t\texception3_%s(opcode, %sa);\n", getv == 2 ? "write" :
"read", name);
printf ("\t\tgoto %s;\n", endlabelstr);
printf ("\t}\n");
@@ -3675,6 +3679,8 @@ static void gen_opcode (unsigned int opcode)
//if (curi->size == sz_long && (curi->smode == Dreg || curi->smode
== Areg))
// flags &= ~GF_APDI;
flags |= dualprefetch ? GF_NOREFILL : 0;
+ if (curi->dmode == Apdi && curi->size == sz_long)
+ flags |= GF_REVERSE;
genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, flags);
if (curi->mnemo == i_MOVEA && curi->size == sz_word)
printf ("\tsrc = (uae_s32)(uae_s16)src;\n");
@@ -3693,7 +3699,12 @@ static void gen_opcode (unsigned int opcode)
single_check_ipl();
}
}
- genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
+ // MOVE EA,-(An) long writes are always reversed. Reads are normal.
+ if (curi->dmode == Apdi && curi->size == sz_long) {
+ genastore_rev("src", curi->dmode, "dstreg", curi->size, "dst");
+ } else {
+ genastore("src", curi->dmode, "dstreg", curi->size, "dst");
+ }
sync_m68k_pc ();
if (dualprefetch) {
fill_prefetch_full_000 ();