From 5ed2a20eaa264c72c1375943dd153c8c05403504 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 15 Jul 2008 17:04:43 +0000 Subject: [PATCH] idle loops adjusted git-svn-id: file:///home/notaz/opt/svn/PicoDrive@549 be3aeb3a-fb24-0410-a615-afba39da0efa --- Pico/Pico.c | 27 ++++++++++++++++++------ Pico/Sek.c | 41 ++++++++++++++++++++++++++++++++---- cpu/Cyclone/tools/idle.s | 45 ++++++++++++++++++---------------------- cpu/fame/famec.c | 4 ++-- cpu/fame/famec_opcodes.h | 24 ++++++++------------- 5 files changed, 89 insertions(+), 52 deletions(-) diff --git a/Pico/Pico.c b/Pico/Pico.c index 5684e99..b5e4e28 100644 --- a/Pico/Pico.c +++ b/Pico/Pico.c @@ -171,16 +171,16 @@ int PicoReset(void) if (Pico.m.dma_xfers == 0 && !(PicoOpt&POPT_DIS_VDP_FIFO)) Pico.m.dma_xfers = rand() & 0x1fff; + SekFinishIdleDet(); + if (PicoAHW & PAHW_MCD) { PicoResetMCD(); return 0; } - else { - // reinit, so that checksum checks pass - SekFinishIdleDet(); - if (!(PicoOpt & POPT_DIS_IDLE_DET)) - SekInitIdleDet(); - } + + // reinit, so that checksum checks pass + if (!(PicoOpt & POPT_DIS_IDLE_DET)) + SekInitIdleDet(); // reset sram state; enable sram access by default if it doesn't overlap with ROM Pico.m.sram_reg=sram_reg&0x14; @@ -315,6 +315,21 @@ void PicoFrame(void) { Pico.m.frame_count++; +#if 0 + if ((Pico.m.frame_count & 0x3f) == 0) + { + extern int idlehit_addrs[], idlehit_counts[]; + int i; + printf("--\n"); + for (i = 0; i < 128 && idlehit_addrs[i] != 0; i++) { + if (idlehit_counts[i] != 0) { + printf("%06x %i %i\n", idlehit_addrs[i], idlehit_counts[i], idlehit_counts[i] >> 6); + idlehit_counts[i] = 0; + } + } + } +#endif + if (PicoAHW & PAHW_MCD) { PicoFrameMCD(); return; diff --git a/Pico/Sek.c b/Pico/Sek.c index 333169c..f72da65 100644 --- a/Pico/Sek.c +++ b/Pico/Sek.c @@ -199,6 +199,25 @@ static int *idledet_addrs = NULL; static int idledet_count = 0, idledet_bads = 0; int idledet_start_frame = 0; +#if 0 +#define IDLE_STATS 1 +unsigned int idlehit_addrs[128], idlehit_counts[128]; + +void SekRegisterIdleHit(unsigned int pc) +{ + int i; + for (i = 0; i < 127 && idlehit_addrs[i]; i++) { + if (idlehit_addrs[i] == pc) { + idlehit_counts[i]++; + return; + } + } + idlehit_addrs[i] = pc; + idlehit_counts[i] = 1; + idlehit_addrs[i+1] = 0; +} +#endif + void SekInitIdleDet(void) { void *tmp = realloc(idledet_addrs, 0x200*4); @@ -210,6 +229,9 @@ void SekInitIdleDet(void) idledet_addrs = tmp; idledet_count = idledet_bads = 0; idledet_start_frame = Pico.m.frame_count + 360; +#ifdef IDLE_STATS + idlehit_addrs[0] = 0; +#endif #ifdef EMU_C68K CycloneInitIdle(); @@ -224,6 +246,10 @@ int SekIsIdleCode(unsigned short *dst, int bytes) // printf("SekIsIdleCode %04x %i\n", *dst, bytes); switch (bytes) { + case 2: + if ((*dst & 0xf000) != 0x6000) // not another branch + return 1; + break; case 4: if ( (*dst & 0xfff8) == 0x4a10 || // tst.b ($aX) // there should be no need to wait (*dst & 0xfff8) == 0x4a28 || // tst.b ($xxxx,a0) // for byte change anywhere @@ -261,13 +287,20 @@ int SekIsIdleCode(unsigned short *dst, int bytes) return 0; } -int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop) +int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop, void *ctx) { -#ifdef EMU_C68K - pc -= PicoCpuCM68k.membase; + int is_main68k = 1; +#if defined(EMU_C68K) + struct Cyclone *cyc = ctx; + is_main68k = cyc == &PicoCpuCM68k; + pc -= cyc->membase; +#elif defined(EMU_F68K) + is_main68k = ctx == &PicoCpuFM68k; #endif pc &= ~0xff000000; - elprintf(EL_IDLE, "idle: patch %06x %04x %04x #%i", pc, oldop, newop, idledet_count); + elprintf(EL_IDLE, "idle: patch %06x %04x %04x %c %c #%i", pc, oldop, newop, + (newop&0x200)?'n':'y', is_main68k?'m':'s', idledet_count); + if (pc > Pico.romsize && !(PicoAHW & PAHW_SVP)) { if (++idledet_bads > 128) return 2; // remove detector return 1; // don't patch diff --git a/cpu/Cyclone/tools/idle.s b/cpu/Cyclone/tools/idle.s index 645ab9a..c865f80 100644 --- a/cpu/Cyclone/tools/idle.s +++ b/cpu/Cyclone/tools/idle.s @@ -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 - diff --git a/cpu/fame/famec.c b/cpu/fame/famec.c index aa0a9d8..8469131 100644 --- a/cpu/fame/famec.c +++ b/cpu/fame/famec.c @@ -5041,8 +5041,8 @@ idle_install: INSTALL_IDLE(0x75f8, 0x67f8, idle_detector_bcc8, 0x6701_idle, 0x6701); INSTALL_IDLE(0x75f6, 0x67f6, idle_detector_bcc8, 0x6701_idle, 0x6701); INSTALL_IDLE(0x75f2, 0x67f2, idle_detector_bcc8, 0x6701_idle, 0x6701); - INSTALL_IDLE(0x7dfe, 0x60fe, idle_detector_dead, 0x6001_idle, 0x6001); - INSTALL_IDLE(0x7dfc, 0x60fc, idle_detector_dead, 0x6001_idle, 0x6001); + INSTALL_IDLE(0x7dfe, 0x60fe, idle_detector_bcc8, 0x6001_idle, 0x6001); + INSTALL_IDLE(0x7dfc, 0x60fc, idle_detector_bcc8, 0x6001_idle, 0x6001); return 0; idle_remove: diff --git a/cpu/fame/famec_opcodes.h b/cpu/fame/famec_opcodes.h index ecbc056..96e4675 100644 --- a/cpu/fame/famec_opcodes.h +++ b/cpu/fame/famec_opcodes.h @@ -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 -- 2.39.2