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 ();




Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/