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",