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
{\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
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
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
// 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
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
.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
.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:
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
-
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
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)
{
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;
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