Re: [hatari-devel] Basic cpu testsuite

[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-devel Archives ]


> - Stuff like the "move sr,d0" vs. "move ccr,d0" ifdeffery of course
>   won't work if the binary should be used for both, 68000 and 68010+
>   CPU levels. We'd need to think of a way to solve that before such
>   a test could be included...
 
The attached patch should solve that. It will install exception handlers that 
immediately terminate the program in tos-less mode, thus solving also the 
problem of bus-errors jumping to nowhere land. The exception handler for 
privilege violation will simulate move sr,<ea> by move ccr,<ea>, just like TOS 
would do.

The trap handlers are set to an rte instruction currently, maybe you want to 
change them to terminate, too, but i haven't tested that yet.
diff -r 6b899cd7e1bd src/tos.c
--- a/src/tos.c	Fri May 25 00:55:30 2018 +0300
+++ b/src/tos.c	Sat May 26 15:24:10 2018 +0200
@@ -667,7 +667,7 @@
 static uint8_t *TOS_FakeRomForTesting(void)
 {
 	uint8_t *pFakeTosMem;
-	uint8_t fake_tos[] = {
+	static uint8_t const fake_tos[] = {
 		0x60, 0x2e,                         /* Branch to 0xe00030 */
 		0x00, 0x00,                         /* TOS version */
 		0x00, 0xe0, 0x00, 0x30,             /* Reset PC value */
@@ -696,7 +696,109 @@
 		0x48, 0x78, TEST_PRG_BASEPAGE >> 8, TEST_PRG_BASEPAGE & 0xff, /* pea 0x1000  (basepage) */
 		0x48, 0x79, 0x00, 0xe0, 0x00, 0x00, /* pea 0xe00000 */
 		0x91, 0xc8,                         /* suba.l a0,a0 */
-		0x4e, 0xf8, TEST_PRG_START >> 8, TEST_PRG_START & 0xff        /* jmp 0x1100 */
+		0x4e, 0xf8, TEST_PRG_START >> 8, TEST_PRG_START & 0xff,       /* jmp 0x1100 */
+
+/* flushCaches: */
+		0x40, 0xe7,                                    /* move.w    sr,-(a7) */
+		0x00, 0x7c, 0x07, 0x00,                        /* ori.w     #$0700,sr */
+		0x4e, 0x7a, 0x00, 0x02,                        /* movec     cacr,d0 */
+		0x00, 0x80, 0x00, 0x00, 0x08, 0x08,            /* ori.l     #$00000808,d0 */
+		0x4e, 0x7b, 0x00, 0x02,                        /* movec     d0,cacr */
+		0x46, 0xdf,                                    /* move.w    (a7)+,sr */
+		0x4e, 0x75,                                    /* rts */
+/* privilege_exception: */
+		0x48, 0xe7, 0xe0, 0x00,                        /* movem.l   d0-d2,-(a7) */
+		0x2f, 0x09,                                    /* move.l    a1,-(a7) */
+		0x2f, 0x08,                                    /* move.l    a0,-(a7) */
+		0x20, 0x6f, 0x00, 0x16,                        /* movea.l   22(a7),a0     ; a0 -> pc */
+		0x30, 0x10,                                    /* move.w    (a0),d0       ; d0 -> current opcode */
+		0x32, 0x00,                                    /* move.w    d0,d1         ; d1 -> save current opcode */
+		0x02, 0x40, 0xff, 0xc0,                        /* andi.w    #$FFC0,d0 */
+		0x0c, 0x40, 0x40, 0xc0,                        /* cmpi.w    #$40C0,d0     ; move SR,<ea>? */
+		0x66, 0x00, 0x00, 0xd4,                        /* bne       pi_back       ; (no -- punt) */
+		0x21, 0xfc, 0x30, 0x00, 0x4e, 0x71, 0x0a, 0x14,/* move.l    #$30004E71,($0A14).w ; move.w d0,d0, nop */
+		0x21, 0xfc, 0x4e, 0x71, 0x4e, 0x75, 0x0a, 0x18,/* move.l    #$4E714E75,($0A18).w ; nop, rts */
+		0x30, 0x01,                                    /* move.w    d1,d0 */
+		0x02, 0x40, 0x00, 0x07,                        /* andi.w    #$0007,d0     ; <ea> register (bit 0..2) */
+		0xe1, 0x48,                                    /* lsl.w     #8,d0 */
+		0xe3, 0x48,                                    /* lsl.w     #1,d0         ; move into bit 9..11 of the destination <ea> */
+		0x81, 0x78, 0x0a, 0x14,                        /* or.w      d0,($0A14).w */
+		0x30, 0x01,                                    /* move.w    d1,d0 */
+		0x02, 0x40, 0x00, 0x38,                        /* andi.w    #$0038,d0     ; <ea> mode (bit 3..5) */
+		0xe7, 0x48,                                    /* lsl.w     #3,d0         ; move into bit 6..8 of the destination <ea> */
+		0x81, 0x78, 0x0a, 0x14,                        /* or.w      d0,($0A14).w  ; generate a MOVE D0,<ea> from the MOVE SR,<ea> opcode */
+		0x74, 0x02,                                    /* moveq.l   #2,d2         ; opcode size = 2 */
+		0x0c, 0x40, 0x01, 0x80,                        /* cmpi.w    #$0180,d0     ; <ea> == d8(An,Xn)? */
+		0x67, 0x00, 0x00, 0xa0,                        /* beq       pi_back       ; not supported -> _term */
+		0x4a, 0x40,                                    /* tst.w     d0            ; <ea> == Dn? */
+		0x67, 0x5a,                                    /* beq.s     int_p4 */
+		0x0c, 0x40, 0x01, 0x40,                        /* cmpi.w    #$0140,d0     ; <ea> == d16(An)? */
+		0x67, 0x1e,                                    /* beq.s     int_p2 */
+		0x0c, 0x40, 0x01, 0xc0,                        /* cmpi.w    #$01C0,d0     ; <ea> == (xxx).w or (xxx).l? */
+		0x66, 0x20,                                    /* bne.s     int_p3 */
+
+/*  <ea> = (xxx).l or (xxx).w */
+		0x02, 0x41, 0x00, 0x07,                        /* andi.w    #$0007,d1     ; register == 0 => (xxx).w */
+		0x67, 0x08,                                    /* beq.s     int_p1 */
+		0x54, 0x42,                                    /* addq.w    #2,d2         ; it is (xxx).l -> opcode size += 2 */
+		0x31, 0xe8, 0x00, 0x04, 0x0a, 0x18,            /* move.w    4(a0),($0A18).w ; move lower word of the absolute address */
+/* int_p1: */
+		0x54, 0x42,                                    /* addq.w    #2,d2         ; opcode size += 2 */
+		0x31, 0xe8, 0x00, 0x02, 0x0a, 0x16,            /* move.w    2(a0),($0A16).w ; move upper word of the absolute address */
+		0x60, 0x5c,                                    /* bra.s     int_p5        ; -> regular destination ea */
+
+/* int_p2: <ea> = d16(An) */
+		0x54, 0x42,                                    /* addq.w    #2,d2         ; opcode size += 2 */
+		0x31, 0xe8, 0x00, 0x02, 0x0a, 0x16,            /* move.w    2(a0),($0A16).w ; move d16 offset */
+/* int_p3: */
+		0x02, 0x41, 0x00, 0x07,                        /* andi.w    #$0007,d1     ; d1 = An from the destination <ea> */
+		0x0c, 0x41, 0x00, 0x07,                        /* cmpi.w    #$0007,d1     ; relative to A7? */
+		0x66, 0x4a,                                    /* bne.s     int_p5        ; no -> regular destination ea */
+		0x4e, 0x69,                                    /* move.l    usp,a1        ; have to use the USP, otherwise we wouldn't have gotten the exception */
+		0x02, 0x78, 0xf3, 0xff, 0x0a, 0x14,            /* andi.w    #$F3FF,($0A14).w ; convert A7-relative into A1-relative destination <ea> */
+		0xd5, 0xaf, 0x00, 0x16,                        /* add.l     d2,22(a7)     ; pc += opcode size */
+		0x61, 0x00, 0xff, 0x50,                        /* bsr       flushCaches   */
+		0x30, 0x2f, 0x00, 0x14,                        /* move.w    20(a7),d0     ; d0 = SR */
+		0x4e, 0xb8, 0x0a, 0x14,                        /* jsr       ($0A14).w     ; execute: MOVE D0,d(A1,Dn); NOP; RTS or MOVE D0,d(A1); NOP; RTS */
+		0x4e, 0x61,                                    /* move.l    a1,usp        ; restore USP, but shouldn't have changed anyway */
+		0x20, 0x5f,                                    /* movea.l   (a7)+,a0      ; restore registers */
+		0x22, 0x5f,                                    /* movea.l   (a7)+,a1 */
+		0x4c, 0xdf, 0x00, 0x07,                        /* movem.l   (a7)+,d0-d2 */
+		0x4e, 0x73,                                    /* rte                     ; continue execution */
+
+/* int_p4: <ea> = Dn */
+		0xd5, 0xaf, 0x00, 0x16,                        /* add.l     d2,22(a7)     ; pc += opcode size */
+		0x00, 0x78, 0x00, 0x10, 0x0a, 0x14,            /* ori.w     #$0010,($0A14).w ; source ea = (A0) */
+		0x61, 0x00, 0xff, 0x2e,                        /* bsr       flushCaches */
+		0x41, 0xef, 0x00, 0x14,                        /* lea.l     20(a7),a0     ; point to SR register to SSP */
+		0x4c, 0xef, 0x00, 0x07, 0x00, 0x08,            /* movem.l   8(a7),d0-d2   ; restore d0-d2 */
+		0x4e, 0xb8, 0x0a, 0x14,                        /* jsr       ($0A14).w     ; execute: MOVE (A0),Dn; NOP; NOP; RTS */
+		0x20, 0x5f,                                    /* movea.l   (a7)+,a0      ; restore registers */
+		0x22, 0x5f,                                    /* movea.l   (a7)+,a1      ; skip d0-d2, because they have already been restored */
+		0xde, 0xfc, 0x00, 0x0c,                        /* adda.w    #$000C,a7     ; continue execution */
+		0x4e, 0x73,                                    /* rte */
+/* int_p5: */
+		0xd5, 0xaf, 0x00, 0x16,                        /* add.l     d2,22(a7)     ; pc += opcode size */
+		0x61, 0x00, 0xff, 0x0e,                        /* bsr       flushCaches */
+		0x20, 0x5f,                                    /* movea.l   (a7)+,a0 */
+		0x22, 0x5f,                                    /* movea.l   (a7)+,a1 */
+		0x30, 0x2f, 0x00, 0x0c,                        /* move.w    12(a7),d0     ; d0 = SR */
+		0x4e, 0xb8, 0x0a, 0x14,                        /* jsr       ($0A14).w     ; execute: MOVE D0,<ea>; ...; RTS */
+		0x4c, 0xdf, 0x00, 0x07,                        /* movem.l   (a7)+,d0-d2   ; restore registers */
+		0x4e, 0x73,                                    /* rte                     ; continue execution */
+/* pi_back: */
+		0x20, 0x5f,                                    /* movea.l   (a7)+,a0      ; restore registers */
+		0x22, 0x5f,                                    /* movea.l   (a7)+,a1 */
+		0x4c, 0xdf, 0x00, 0x07,                        /* movem.l   (a7)+,d0-d2 */
+/* illegal instruction => _term */
+
+/* fatal_exit: */
+		0x70, 0x01,                         /* moveq #1,d0 */
+		0x3f, 0x00,                         /* move.w d0,-(a7) */
+		0x3f, 0x3c, 0x00, 0x4c,             /* move.w #76,-(a7) */
+		0x4e, 0x41,                         /* trap #1 */
+		0x4e, 0x75,                         /* rts */
+		0x4e, 0x73                          /* rte */
 	};
 
 	/* We don't have a proper memory detection code in above init code,
@@ -716,6 +818,65 @@
 	return pFakeTosMem;
 }
 
+
+static void TOS_FakeExceptionHandlers(void)
+{
+	Uint32 i;
+
+#define fatal_exit (TosAddress + TosSize - 14)
+#define privilege_exception (fatal_exit - 246)
+#define rts (TosAddress + TosSize - 4)
+#define rte (TosAddress + TosSize - 2)
+
+	/*
+	 * setup exception vectors
+	 */
+	for (i = 0x8; i < 0x400; i += 4)
+		STMemory_WriteLong(i, rte);
+
+	STMemory_WriteLong(0x008, fatal_exit); /* bus error */
+	STMemory_WriteLong(0x00c, fatal_exit); /* address error */
+	STMemory_WriteLong(0x010, fatal_exit); /* illegal instruction */
+	STMemory_WriteLong(0x014, rte); /* zero divide */
+	STMemory_WriteLong(0x018, rte); /* CHK */
+	STMemory_WriteLong(0x01C, fatal_exit); /* TRAPcc */
+	STMemory_WriteLong(0x020, privilege_exception); /* privilege violation */
+	STMemory_WriteLong(0x024, fatal_exit); /* trace */
+	STMemory_WriteLong(0x028, fatal_exit); /* linea */
+	STMemory_WriteLong(0x02c, fatal_exit); /* linef */
+	STMemory_WriteLong(0x034, fatal_exit); /* coprocessor protocol violation */
+	STMemory_WriteLong(0x038, fatal_exit); /* format error */
+	STMemory_WriteLong(0x03c, fatal_exit); /* uninitialized interrupt */
+	STMemory_WriteLong(0x064, rte); /* auto vector #1 */
+	STMemory_WriteLong(0x068, rte); /* auto vector #2 */
+	STMemory_WriteLong(0x06c, rte); /* auto vector #3 */
+	STMemory_WriteLong(0x070, rte); /* auto vector #4 */
+	STMemory_WriteLong(0x074, rte); /* auto vector #5 */
+	STMemory_WriteLong(0x078, rte); /* auto vector #6 */
+	STMemory_WriteLong(0x07c, rte); /* auto vector #7 */
+	STMemory_WriteLong(0x080, rte); /* trap #0 */
+	STMemory_WriteLong(0x084, rte); /* trap #1 */
+	STMemory_WriteLong(0x088, rte); /* trap #2 */
+	STMemory_WriteLong(0x08c, rte); /* trap #3 */
+	STMemory_WriteLong(0x090, rte); /* trap #4 */
+	STMemory_WriteLong(0x094, rte); /* trap #5 */
+	STMemory_WriteLong(0x098, rte); /* trap #6 */
+	STMemory_WriteLong(0x09c, rte); /* trap #7 */
+	STMemory_WriteLong(0x0a0, rte); /* trap #8 */
+	STMemory_WriteLong(0x0a4, rte); /* trap #9 */
+	STMemory_WriteLong(0x0a8, rte); /* trap #10 */
+	STMemory_WriteLong(0x0ac, rte); /* trap #11 */
+	STMemory_WriteLong(0x0b0, rte); /* trap #12 */
+	STMemory_WriteLong(0x0b4, rte); /* trap #13 */
+	STMemory_WriteLong(0x0b8, rte); /* trap #14 */
+	STMemory_WriteLong(0x0bc, rte); /* trap #15 */
+
+#undef rts
+#undef rte
+#undef fatal_exit
+#undef privilege_exception
+}
+
 /**
  * Load TOS Rom image file into ST memory space and fix image so it can be
  * emulated correctly.  Pre TOS 1.06 are loaded at 0xFC0000 and later ones
@@ -808,6 +969,7 @@
 	/* Load test program (has to be done after memory has been cleared */
 	if (!bUseTos)
 	{
+		TOS_FakeExceptionHandlers();
 		if (psTestPrg)
 		{
 			Log_Printf(LOG_DEBUG, "Loading '%s' to 0x%x.\n",


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