tests and tools from PicoDrive
authornotaz <notasas@gmail.com>
Sun, 16 Jun 2013 16:48:40 +0000 (19:48 +0300)
committernotaz <notasas@gmail.com>
Sun, 16 Jun 2013 16:48:40 +0000 (19:48 +0300)
12 files changed:
tests/crash_cyclone.bin [new file with mode: 0644]
tests/test_abcd.bin [new file with mode: 0644]
tests/test_cmpm.bin [new file with mode: 0644]
tests/test_div.bin [new file with mode: 0644]
tests/test_misc2_gen.c [new file with mode: 0644]
tests/test_negx.bin [new file with mode: 0644]
tests/test_rol.bin [new file with mode: 0644]
tests/test_shift.bin [new file with mode: 0644]
tests/test_trace.bin [new file with mode: 0644]
tests/test_trace.s [new file with mode: 0644]
tools/idle.h [new file with mode: 0644]
tools/idle.s [new file with mode: 0644]

diff --git a/tests/crash_cyclone.bin b/tests/crash_cyclone.bin
new file mode 100644 (file)
index 0000000..dfa0276
Binary files /dev/null and b/tests/crash_cyclone.bin differ
diff --git a/tests/test_abcd.bin b/tests/test_abcd.bin
new file mode 100644 (file)
index 0000000..fe25040
Binary files /dev/null and b/tests/test_abcd.bin differ
diff --git a/tests/test_cmpm.bin b/tests/test_cmpm.bin
new file mode 100644 (file)
index 0000000..e761857
Binary files /dev/null and b/tests/test_cmpm.bin differ
diff --git a/tests/test_div.bin b/tests/test_div.bin
new file mode 100644 (file)
index 0000000..6e9cb77
Binary files /dev/null and b/tests/test_div.bin differ
diff --git a/tests/test_misc2_gen.c b/tests/test_misc2_gen.c
new file mode 100644 (file)
index 0000000..108156b
--- /dev/null
@@ -0,0 +1,119 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+static FILE *f;
+
+#define bswap16(x) (x=(unsigned short)((x<<8)|(x>>8)))
+#define bswap32(x) (x=((x<<24)|((x<<8)&0xff0000)|((x>>8)&0x00ff00)|((unsigned)x>>24)))
+
+static void write_op(unsigned short op, unsigned short word0, unsigned short word1, unsigned short word2)
+{
+       bswap16(op);
+       bswap16(word0);
+       bswap16(word1);
+       bswap16(word2);
+
+       fwrite(&op,    1, sizeof(op), f);
+       fwrite(&word0, 1, sizeof(word0), f);
+       fwrite(&word1, 1, sizeof(word1), f);
+       fwrite(&word2, 1, sizeof(word2), f);
+}
+
+static void write32(unsigned int a)
+{
+       bswap32(a);
+       fwrite(&a,     1, sizeof(a),  f);
+}
+
+static int op_check(unsigned short op)
+{
+       if ((op&0xf000) == 0x6000) return 0; // Bxx
+       if ((op&0xf0f8) == 0x50c8) return 0; // DBxx
+       if ((op&0xff80) == 0x4e80) return 0; // Jsr
+       if ((op&0xf000) == 0xa000) return 0; // a-line
+       if ((op&0xf000) == 0xf000) return 0; // f-line
+       if ((op&0xfff8)==0x4e70&&op!=0x4e71&&op!=0x4e76) return 0; // reset, rte, rts
+
+       if ((op&0x3f) >= 0x28) op = (op&~0x3f) | (rand() % 0x28);
+       return 1;
+}
+
+static unsigned short safe_rand(void)
+{
+       unsigned short op;
+
+       /* avoid branch opcodes */
+       do
+       {
+               op = rand();
+       }
+       while (!op_check(op));
+
+       return op;
+}
+
+int main()
+{
+       int i, op;
+
+       srand(time(0));
+
+       f = fopen("test_misc2.bin", "wb");
+       if (!f) return 1;
+
+       write32(0x00ff8000); // stack
+       write32(0x300); // IP
+
+       for (i=0x100/4-2; i; i--)
+       {
+               write32(0x200+i*4); // exception vectors
+       }
+
+       for (i=0x100/4; i; i--)
+       {
+               write32(0); // pad
+       }
+
+       for (i=0x100/4; i; i--)
+       {
+               write32(0x4e734e73); // fill with rte instructions
+       }
+
+       for (op = 0; op < 0x10000; op++)
+       {
+               if ((op&0xf000) == 0x6000) // Bxx
+               {
+                       if ((op&0x00ff) == 0)
+                               write_op(op, 6, 0, 0);
+               }
+               else if ((op&0xf0f8)==0x50c8) // DBxx
+               {
+                       write_op(op, 6, 0, 0);
+               }
+               else if ((op&0xff80)==0x4e80) // Jsr
+               {
+                       int addr = 0x300 + op*8 + 8;
+                       if ((op&0x3f) == 0x39)
+                               write_op(op, addr >> 16, addr & 0xffff, 0);
+               }
+               else if ((op&0xf000)==0xa000 || (op&0xf000)==0xf000) // a-line, f-line
+               {
+                       if (op != 0xa000 && op != 0xf000) continue;
+               }
+               else if ((op&0xfff8)==0x4e70&&op!=0x4e71&&op!=0x4e76); // rte, rts, stop, reset
+               else
+               {
+                       write_op(op, safe_rand(), safe_rand(), safe_rand());
+               }
+       }
+
+       // jump to the beginning
+       write_op(0x4ef8, 0x300, 0x4ef8, 0x300);
+       write_op(0x4ef8, 0x300, 0x4ef8, 0x300);
+
+       fclose(f);
+       return 0;
+}
+
diff --git a/tests/test_negx.bin b/tests/test_negx.bin
new file mode 100644 (file)
index 0000000..1f6e6cf
Binary files /dev/null and b/tests/test_negx.bin differ
diff --git a/tests/test_rol.bin b/tests/test_rol.bin
new file mode 100644 (file)
index 0000000..0cb0a41
Binary files /dev/null and b/tests/test_rol.bin differ
diff --git a/tests/test_shift.bin b/tests/test_shift.bin
new file mode 100644 (file)
index 0000000..c364f21
Binary files /dev/null and b/tests/test_shift.bin differ
diff --git a/tests/test_trace.bin b/tests/test_trace.bin
new file mode 100644 (file)
index 0000000..e9ca5fa
Binary files /dev/null and b/tests/test_trace.bin differ
diff --git a/tests/test_trace.s b/tests/test_trace.s
new file mode 100644 (file)
index 0000000..b6d8421
--- /dev/null
@@ -0,0 +1,140 @@
+| Processor:        68K\r
+| Target Assembler: 680x0 Assembler by GNU project\r
+\r
+| ___________________________________________________________________________\r
+\r
+| Segment type: Pure code\r
+| segment "ROM"\r
+dword_0:        .long 0                 | DATA XREF: ROM:00007244\19r\r
+                                        | sub_764E+3E\19o ...\r
+                                        | initial interrupt stack pointer\r
+dword_4:        .long _start            | DATA XREF: ROM:00007248\19r\r
+                                        | ROM:000142C2\19w\r
+                                        | reset initial PC\r
+dword_8:        .long 0x4DE             | DATA XREF: sub_20050+B54\19w\r
+                .long 0x490\r
+                .long 0x4AA             | illegal instruction\r
+                .long 0x4C4\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long _trace            | trace\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x548             | Level 1 Interrupt Autovector\r
+                .long 0x548             | 2 = ext interrupt\r
+                .long 0x548\r
+                .long 0x592             | 4 = horizontal interrupt?\r
+                .long 0x548\r
+                .long 0x594             | 6 = verticai interrupt?\r
+                .long 0x552\r
+dword_80:       .long 0x45C             | DATA XREF: ROM:00152F29\19o\r
+                                        | trap vector table? trap 0?\r
+                .long 0x1738\r
+                .long 0x171C\r
+                .long 0x1754\r
+                .long 0x1700\r
+                .long 0x556\r
+                .long 0x57A\r
+                .long 0x548\r
+                .long 0x548\r
+                .long 0x7CE             | 9\r
+                .long 0x548\r
+                .long 0x548\r
+                .long 0x548\r
+                .long 0x548\r
+                .long 0x548\r
+                .long 0x548\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+                .long 0x4DE\r
+aSegaGenesis:   .ascii "SEGA GENESIS    " | DATA XREF: ROM:00045C6A\19o\r
+aCSega1994_jul: .ascii "(C)SEGA 1994.JUL"\r
+aDumpedByTsd:   .ascii "Dumped By TSD                                   "\r
+aShiningForce2: .ascii "SHINING FORCE 2                                 "\r
+aGmMk131500:    .ascii "GM MK-1315 -00"\r
+                .word 0x8921            | checksum\r
+aJ:             .ascii "J               " | IO_Support\r
+                .long 0                 | Rom_Start_Adress\r
+dword_1A4:      .long 0x1FFFFF          | DATA XREF: sub_28008+F66\19o\r
+                                        | Rom_End_Adress\r
+                .long 0xFF0000          | Ram_Start_Adress\r
+                .long 0xFFFFFF          | Ram_End_Adress\r
+aRaa:           .ascii "RA° "<0>" "<0><1><0>" ?"<0xFF> | Modem_Infos\r
+                .ascii "                                        "\r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+aU:             .ascii "U  "            | Countries\r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+                .byte 0x20 |  \r
+_trace:\r
+  nop\r
+  nop\r
+  rte\r
+\r
+.globl _start\r
+_start:\r
+  move.l   #0xFFFFFFFF, %d0\r
+  move.l   #0xFFFFFFFF, %d1\r
+  move.w   #0xa711, %sr\r
+  move.l   #0x1, %d2\r
+  move.l   #0x8000, %d3\r
+  negx.l   %d0\r
+  negx.l   %d1\r
+  move.w   #0x270f, %sr\r
+  negx.b   %d2\r
+  negx.w   %d3\r
+_loop:\r
+  bra      _loop\r
+\r
+  nop\r
+  nop\r
+  nop\r
+  nop\r
diff --git a/tools/idle.h b/tools/idle.h
new file mode 100644 (file)
index 0000000..254cc57
--- /dev/null
@@ -0,0 +1,3 @@
+
+void CycloneInitIdle(void);
+void CycloneFinishIdle(void);
diff --git a/tools/idle.s b/tools/idle.s
new file mode 100644 (file)
index 0000000..a8b7cca
--- /dev/null
@@ -0,0 +1,176 @@
+@ vim:filetype=armasm
+
+@ ranges/opcodes (idle, normal):
+@ 71xx, 73xx  - bne.s (8bit offset)
+@ 75xx, 77xx  - beq.s (8bit offset)
+@ 7dxx, 7fxx  - bra.s (8bit offset)
+
+.data
+.align 2
+
+have_patches:
+  .word 0
+
+.equ patch_desc_table_size, 10
+
+patch_desc_table:
+  .word (0x71fa<<16) | 0x66fa, idle_detector_bcc8, idle_bne, Op6601  @ bne.s
+  .word (0x71f8<<16) | 0x66f8, idle_detector_bcc8, idle_bne, Op6601  @ bne.s
+  .word (0x71f6<<16) | 0x66f6, idle_detector_bcc8, idle_bne, Op6601  @ bne.s
+  .word (0x71f2<<16) | 0x66f2, idle_detector_bcc8, idle_bne, Op6601  @ bne.s
+  .word (0x75fa<<16) | 0x67fa, idle_detector_bcc8, idle_beq, Op6701  @ beq.s
+  .word (0x75f8<<16) | 0x67f8, idle_detector_bcc8, idle_beq, Op6701  @ beq.s
+  .word (0x75f6<<16) | 0x67f6, idle_detector_bcc8, idle_beq, Op6701  @ beq.s
+  .word (0x75f2<<16) | 0x67f2, idle_detector_bcc8, idle_beq, Op6701  @ beq.s
+  .word (0x7dfe<<16) | 0x60fe, idle_detector_bcc8, idle_bra, Op6001  @ bra.s
+  .word (0x7dfc<<16) | 0x60fc, idle_detector_bcc8, idle_bra, Op6001  @ bra.s
+
+
+.text
+.align 2
+
+
+.global CycloneInitIdle
+
+CycloneInitIdle:
+    ldr     r3, =CycloneJumpTab
+    ldr     r2, =patch_desc_table
+    mov     r12,#patch_desc_table_size
+
+cii_loop:
+    ldrh    r0, [r2]
+    ldr     r1, [r2, #4]           @ detector
+    str     r1, [r3, r0, lsl #2]
+    ldrh    r0, [r2, #2]
+    ldr     r1, [r2, #8]           @ idle
+    add     r0, r3, r0, lsl #2
+    str     r1, [r0]
+    ldr     r1, [r2, #12]          @ normal
+    str     r1, [r0, #0x800]
+    add     r2, r2, #16
+    subs    r12,r12,#1
+    bgt     cii_loop
+
+    ldr     r0, =have_patches
+    mov     r1, #1
+    str     r1, [r0]
+    bx      lr
+
+
+.global CycloneFinishIdle
+
+CycloneFinishIdle:
+    ldr     r0, =have_patches
+    ldr     r0, [r0]
+    tst     r0, r0
+    bxeq    lr
+
+    ldr     r3, =CycloneJumpTab
+    ldr     r2, =patch_desc_table
+    mov     r12,#patch_desc_table_size
+
+cfi_loop:
+    ldrh    r0, [r2]
+    ldr     r1, [r2, #12]         @ normal
+    str     r1, [r3, r0, lsl #2]
+    ldrh    r0, [r2, #2]
+    ldr     r1, =Op____
+    add     r0, r3, r0, lsl #2
+    str     r1, [r0]
+    str     r1, [r0, #0x800]
+    add     r2, r2, #16
+    subs    r12,r12,#1
+    bgt     cfi_loop
+
+    ldr     r0, =have_patches
+    mov     r1, #0
+    str     r1, [r0]
+    bx      lr
+
+
+
+.macro inc_counter cond
+@    ldr\cond r0, [r7, #0x60]
+@    mov     r11,lr
+@    sub     r0, r4, r0
+@    sub     r0, r0, #2
+@    bl\cond SekRegisterIdleHit
+@    mov     lr, r11
+.endm
+
+idle_bra:
+    mov     r5, #2
+    inc_counter
+    b       Op6001
+
+idle_bne:
+    msr     cpsr_flg, r10
+    movne   r5, #2                @ 2 is intentional due to strange timing issues
+    inc_counter ne
+    b       Op6601
+
+idle_beq:
+    msr     cpsr_flg, r10 ;@ ARM flags = 68000 flags
+    moveq   r5, #2
+    inc_counter eq
+    b       Op6701
+
+
+@ @@@ @
+
+idle_detector_bcc8:
+    ldr     r0, =(Pico+0x22208)   @ Pico.m
+    ldr     r1, =idledet_start_frame
+    ldr     r0, [r0, #0x1c]       @ ..frame_count
+    ldr     r1, [r1]
+    cmp     r0, r1
+    blt     exit_detector         @ not yet
+
+    mov     r0, r8, asl #24       @ Shift 8-bit signed offset up...
+    add     r0, r4, r0, asr #24   @ jump dest
+    bic     r0, r0, #1
+
+    mov     r1, #0
+    sub     r1, r1, r8, lsl #24
+    mov     r1, r1, lsr #24
+    sub     r1, r1, #2
+    bic     r1, r1, #1
+
+    bl      SekIsIdleCode
+    tst     r0, r0
+    and     r2, r8, #0x00ff
+    orr     r2, r2, #0x7100
+    orreq   r2, r2, #0x0200
+    mov     r0, r8, lsr #8
+    cmp     r0, #0x66
+    orrgt   r2, r2, #0x0400       @ 67xx (beq)
+    orrlt   r2, r2, #0x0c00       @ 60xx (bra)
+
+    @ r2 = patch_opcode
+    sub     r0, r4, #2
+    ldrh    r1, [r0]
+    mov     r11,r2
+    mov     r3, r7
+    bl      SekRegisterIdlePatch
+    cmp     r0, #1                @ 0 - ok to patch, 1 - no patch, 2 - remove detector
+    strlth  r11,[r4, #-2]
+    ble     exit_detector
+
+    @ remove detector from Cyclone
+    mov     r0, r8, lsr #8
+    cmp     r0, #0x66
+    ldrlt   r1, =Op6001
+    ldreq   r1, =Op6601
+    ldrgt   r1, =Op6701
+
+    ldr     r3, =CycloneJumpTab
+    str     r1, [r3, r8, lsl #2]
+    bx      r1
+
+exit_detector:
+    mov     r0, r8, lsr #8
+    cmp     r0, #0x66
+    blt     Op6001
+    beq     Op6601
+    b       Op6701
+