idle loops adjusted
authornotaz <notasas@gmail.com>
Tue, 15 Jul 2008 17:04:43 +0000 (17:04 +0000)
committernotaz <notasas@gmail.com>
Tue, 15 Jul 2008 17:04:43 +0000 (17:04 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@549 be3aeb3a-fb24-0410-a615-afba39da0efa

Pico/Pico.c
Pico/Sek.c
cpu/Cyclone/tools/idle.s
cpu/fame/famec.c
cpu/fame/famec_opcodes.h

index 5684e99..b5e4e28 100644 (file)
@@ -171,16 +171,16 @@ int PicoReset(void)
   if (Pico.m.dma_xfers == 0 && !(PicoOpt&POPT_DIS_VDP_FIFO))\r
     Pico.m.dma_xfers = rand() & 0x1fff;\r
 \r
+  SekFinishIdleDet();\r
+\r
   if (PicoAHW & PAHW_MCD) {\r
     PicoResetMCD();\r
     return 0;\r
   }\r
-  else {\r
-    // reinit, so that checksum checks pass\r
-    SekFinishIdleDet();\r
-    if (!(PicoOpt & POPT_DIS_IDLE_DET))\r
-      SekInitIdleDet();\r
-  }\r
+\r
+  // reinit, so that checksum checks pass\r
+  if (!(PicoOpt & POPT_DIS_IDLE_DET))\r
+    SekInitIdleDet();\r
 \r
   // reset sram state; enable sram access by default if it doesn't overlap with ROM\r
   Pico.m.sram_reg=sram_reg&0x14;\r
@@ -315,6 +315,21 @@ void PicoFrame(void)
 {\r
   Pico.m.frame_count++;\r
 \r
+#if 0\r
+  if ((Pico.m.frame_count & 0x3f) == 0)\r
+  {\r
+    extern int idlehit_addrs[], idlehit_counts[];\r
+    int i;\r
+    printf("--\n");\r
+    for (i = 0; i < 128 && idlehit_addrs[i] != 0; i++) {\r
+      if (idlehit_counts[i] != 0) {\r
+        printf("%06x %i %i\n", idlehit_addrs[i], idlehit_counts[i],  idlehit_counts[i] >> 6);\r
+        idlehit_counts[i] = 0;\r
+      }\r
+    }\r
+  }\r
+#endif\r
+\r
   if (PicoAHW & PAHW_MCD) {\r
     PicoFrameMCD();\r
     return;\r
index 333169c..f72da65 100644 (file)
@@ -199,6 +199,25 @@ static int *idledet_addrs = NULL;
 static int idledet_count = 0, idledet_bads = 0;\r
 int idledet_start_frame = 0;\r
 \r
+#if 0\r
+#define IDLE_STATS 1\r
+unsigned int idlehit_addrs[128], idlehit_counts[128];\r
+\r
+void SekRegisterIdleHit(unsigned int pc)\r
+{\r
+  int i;\r
+  for (i = 0; i < 127 && idlehit_addrs[i]; i++) {\r
+    if (idlehit_addrs[i] == pc) {\r
+      idlehit_counts[i]++;\r
+      return;\r
+    }\r
+  }\r
+  idlehit_addrs[i] = pc;\r
+  idlehit_counts[i] = 1;\r
+  idlehit_addrs[i+1] = 0;\r
+}\r
+#endif\r
+\r
 void SekInitIdleDet(void)\r
 {\r
   void *tmp = realloc(idledet_addrs, 0x200*4);\r
@@ -210,6 +229,9 @@ void SekInitIdleDet(void)
     idledet_addrs = tmp;\r
   idledet_count = idledet_bads = 0;\r
   idledet_start_frame = Pico.m.frame_count + 360;\r
+#ifdef IDLE_STATS\r
+  idlehit_addrs[0] = 0;\r
+#endif\r
 \r
 #ifdef EMU_C68K\r
   CycloneInitIdle();\r
@@ -224,6 +246,10 @@ int SekIsIdleCode(unsigned short *dst, int bytes)
   // printf("SekIsIdleCode %04x %i\n", *dst, bytes);\r
   switch (bytes)\r
   {\r
+    case 2:\r
+      if ((*dst & 0xf000) != 0x6000)     // not another branch\r
+        return 1;\r
+      break;\r
     case 4:\r
       if (  (*dst & 0xfff8) == 0x4a10 || // tst.b ($aX)      // there should be no need to wait\r
             (*dst & 0xfff8) == 0x4a28 || // tst.b ($xxxx,a0) // for byte change anywhere\r
@@ -261,13 +287,20 @@ int SekIsIdleCode(unsigned short *dst, int bytes)
   return 0;\r
 }\r
 \r
-int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop)\r
+int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop, void *ctx)\r
 {\r
-#ifdef EMU_C68K\r
-  pc -= PicoCpuCM68k.membase;\r
+  int is_main68k = 1;\r
+#if   defined(EMU_C68K)\r
+  struct Cyclone *cyc = ctx;\r
+  is_main68k = cyc == &PicoCpuCM68k;\r
+  pc -= cyc->membase;\r
+#elif defined(EMU_F68K)\r
+  is_main68k = ctx == &PicoCpuFM68k;\r
 #endif\r
   pc &= ~0xff000000;\r
-  elprintf(EL_IDLE, "idle: patch %06x %04x %04x #%i", pc, oldop, newop, idledet_count);\r
+  elprintf(EL_IDLE, "idle: patch %06x %04x %04x %c %c #%i", pc, oldop, newop,\r
+    (newop&0x200)?'n':'y', is_main68k?'m':'s', idledet_count);\r
+\r
   if (pc > Pico.romsize && !(PicoAHW & PAHW_SVP)) {\r
     if (++idledet_bads > 128) return 2; // remove detector\r
     return 1; // don't patch\r
index 645ab9a..c865f80 100644 (file)
@@ -22,8 +22,8 @@ patch_desc_table:
   .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_dead, idle_bra, Op6001  @ bra.s
-  .word (0x7dfc<<16) | 0x60fc, idle_detector_dead, idle_bra, Op6001  @ bra.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
@@ -90,10 +90,12 @@ cfi_loop:
 
 
 .macro inc_counter cond
-@    ldr     r0, =idle_hit_counter
-@    ldr     r1, [r0]
-@    add     r1, r1, #1
-@    str\cond r1, [r0]
+@    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:
@@ -139,43 +141,36 @@ idle_detector_bcc8:
     and     r2, r8, #0x00ff
     orr     r2, r2, #0x7100
     orreq   r2, r2, #0x0200
-    tst     r8, #0x0100           @ 67xx (beq)?
-    orrne   r2, r2, #0x0400
+    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
-    tst     r8, #0x0100           @ 67xx (beq)?
+    mov     r0, r8, lsr #8
+    cmp     r0, #0x66
+    ldrlt   r1, =Op6001
     ldreq   r1, =Op6601
-    ldrne   r1, =Op6701
+    ldrgt   r1, =Op6701
 
     ldr     r3, =CycloneJumpTab
     str     r1, [r3, r8, lsl #2]
     bx      r1
 
 exit_detector:
-    tst     r8, #0x0100           @ 67xx (beq)?
+    mov     r0, r8, lsr #8
+    cmp     r0, #0x66
+    blt     Op6001
     beq     Op6601
     b       Op6701
 
-
-idle_detector_dead:
-    @ patch without further questions
-    and     r2, r8, #0x00ff
-    orr     r2, r2, #0x7d00
-    sub     r0, r4, #2
-    ldrh    r1, [r0]
-    mov     r11,r2
-    bl      SekRegisterIdlePatch
-    strh    r11,[r4, #-2]
-    b       Op6001
-
-.pool
-
index aa0a9d8..8469131 100644 (file)
@@ -5041,8 +5041,8 @@ idle_install:
        INSTALL_IDLE(0x75f8, 0x67f8, idle_detector_bcc8, 0x6701_idle, 0x6701);\r
        INSTALL_IDLE(0x75f6, 0x67f6, idle_detector_bcc8, 0x6701_idle, 0x6701);\r
        INSTALL_IDLE(0x75f2, 0x67f2, idle_detector_bcc8, 0x6701_idle, 0x6701);\r
-       INSTALL_IDLE(0x7dfe, 0x60fe, idle_detector_dead, 0x6001_idle, 0x6001);\r
-       INSTALL_IDLE(0x7dfc, 0x60fc, idle_detector_dead, 0x6001_idle, 0x6001);\r
+       INSTALL_IDLE(0x7dfe, 0x60fe, idle_detector_bcc8, 0x6001_idle, 0x6001);\r
+       INSTALL_IDLE(0x7dfc, 0x60fc, idle_detector_bcc8, 0x6001_idle, 0x6001);\r
        return 0;\r
 \r
 idle_remove:\r
index ecbc056..96e4675 100644 (file)
@@ -40013,7 +40013,7 @@ RET(8)
 
 
 extern int SekIsIdleCode(unsigned short *dst, int bytes);
-extern int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop);
+extern int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop, void *ctx);
 
 OPCODE(idle_detector_bcc8)
 {
@@ -40032,18 +40032,22 @@ OPCODE(idle_detector_bcc8)
        ret = SekIsIdleCode(dest_pc, bytes);
        newop = (Opcode & 0xfe) | 0x7100;
        if (!ret) newop |= 0x200;
-       if (Opcode & 0x0100) newop |= 0x400; // beq
+       if (  Opcode & 0x0100)  newop |= 0x400; // beq
+       if (!(Opcode & 0x0f00)) newop |= 0xc00; // bra
 
-       ret = SekRegisterIdlePatch(GET_PC - 2, Opcode, newop);
+       ret = SekRegisterIdlePatch(GET_PC - 2, Opcode, newop, &m68kcontext);
        switch (ret)
        {
                case 0: PC[-1] = newop; break;
                case 1: break;
-               case 2: JumpTable[Opcode] = (Opcode & 0x0100) ? CAST_OP(0x6701) : CAST_OP(0x6601); break;
+               case 2: JumpTable[Opcode] = (Opcode & 0x0f00) ?
+                               ((Opcode & 0x0100) ? CAST_OP(0x6701) : CAST_OP(0x6601)) :
+                               CAST_OP(0x6001); break;
        }
 
 end:
-       cond_true = (Opcode & 0x0100) ? !flag_NotZ : flag_NotZ; // beq?
+       if ((Opcode & 0xff00) == 0x6000) cond_true = 1;
+       else cond_true = (Opcode & 0x0100) ? !flag_NotZ : flag_NotZ; // beq?
        if (cond_true)
        {
                PC = dest_pc;
@@ -40052,14 +40056,4 @@ end:
 RET(8)
 }
 
-OPCODE(idle_detector_dead)
-{
-       // patch without further questions
-       int newop = 0x7d00 | (Opcode & 0xff);
-       PC[-1] = newop;
-       SekRegisterIdlePatch(GET_PC - 2, Opcode, newop);
-
-       PC += ((s8)(Opcode & 0xFE)) >> 1;
-RET(10)
-}
 #endif // PICODRIVE_HACK