mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
idle loops adjusted
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@549 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
parent
1413b9a118
commit
5ed2a20eaa
5 changed files with 89 additions and 52 deletions
21
Pico/Pico.c
21
Pico/Pico.c
|
@ -171,16 +171,16 @@ int PicoReset(void)
|
||||||
if (Pico.m.dma_xfers == 0 && !(PicoOpt&POPT_DIS_VDP_FIFO))
|
if (Pico.m.dma_xfers == 0 && !(PicoOpt&POPT_DIS_VDP_FIFO))
|
||||||
Pico.m.dma_xfers = rand() & 0x1fff;
|
Pico.m.dma_xfers = rand() & 0x1fff;
|
||||||
|
|
||||||
|
SekFinishIdleDet();
|
||||||
|
|
||||||
if (PicoAHW & PAHW_MCD) {
|
if (PicoAHW & PAHW_MCD) {
|
||||||
PicoResetMCD();
|
PicoResetMCD();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// reinit, so that checksum checks pass
|
// reinit, so that checksum checks pass
|
||||||
SekFinishIdleDet();
|
|
||||||
if (!(PicoOpt & POPT_DIS_IDLE_DET))
|
if (!(PicoOpt & POPT_DIS_IDLE_DET))
|
||||||
SekInitIdleDet();
|
SekInitIdleDet();
|
||||||
}
|
|
||||||
|
|
||||||
// reset sram state; enable sram access by default if it doesn't overlap with ROM
|
// reset sram state; enable sram access by default if it doesn't overlap with ROM
|
||||||
Pico.m.sram_reg=sram_reg&0x14;
|
Pico.m.sram_reg=sram_reg&0x14;
|
||||||
|
@ -315,6 +315,21 @@ void PicoFrame(void)
|
||||||
{
|
{
|
||||||
Pico.m.frame_count++;
|
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) {
|
if (PicoAHW & PAHW_MCD) {
|
||||||
PicoFrameMCD();
|
PicoFrameMCD();
|
||||||
return;
|
return;
|
||||||
|
|
41
Pico/Sek.c
41
Pico/Sek.c
|
@ -199,6 +199,25 @@ static int *idledet_addrs = NULL;
|
||||||
static int idledet_count = 0, idledet_bads = 0;
|
static int idledet_count = 0, idledet_bads = 0;
|
||||||
int idledet_start_frame = 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 SekInitIdleDet(void)
|
||||||
{
|
{
|
||||||
void *tmp = realloc(idledet_addrs, 0x200*4);
|
void *tmp = realloc(idledet_addrs, 0x200*4);
|
||||||
|
@ -210,6 +229,9 @@ void SekInitIdleDet(void)
|
||||||
idledet_addrs = tmp;
|
idledet_addrs = tmp;
|
||||||
idledet_count = idledet_bads = 0;
|
idledet_count = idledet_bads = 0;
|
||||||
idledet_start_frame = Pico.m.frame_count + 360;
|
idledet_start_frame = Pico.m.frame_count + 360;
|
||||||
|
#ifdef IDLE_STATS
|
||||||
|
idlehit_addrs[0] = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef EMU_C68K
|
#ifdef EMU_C68K
|
||||||
CycloneInitIdle();
|
CycloneInitIdle();
|
||||||
|
@ -224,6 +246,10 @@ int SekIsIdleCode(unsigned short *dst, int bytes)
|
||||||
// printf("SekIsIdleCode %04x %i\n", *dst, bytes);
|
// printf("SekIsIdleCode %04x %i\n", *dst, bytes);
|
||||||
switch (bytes)
|
switch (bytes)
|
||||||
{
|
{
|
||||||
|
case 2:
|
||||||
|
if ((*dst & 0xf000) != 0x6000) // not another branch
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if ( (*dst & 0xfff8) == 0x4a10 || // tst.b ($aX) // there should be no need to wait
|
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
|
(*dst & 0xfff8) == 0x4a28 || // tst.b ($xxxx,a0) // for byte change anywhere
|
||||||
|
@ -261,13 +287,20 @@ int SekIsIdleCode(unsigned short *dst, int bytes)
|
||||||
return 0;
|
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
|
int is_main68k = 1;
|
||||||
pc -= PicoCpuCM68k.membase;
|
#if defined(EMU_C68K)
|
||||||
|
struct Cyclone *cyc = ctx;
|
||||||
|
is_main68k = cyc == &PicoCpuCM68k;
|
||||||
|
pc -= cyc->membase;
|
||||||
|
#elif defined(EMU_F68K)
|
||||||
|
is_main68k = ctx == &PicoCpuFM68k;
|
||||||
#endif
|
#endif
|
||||||
pc &= ~0xff000000;
|
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 (pc > Pico.romsize && !(PicoAHW & PAHW_SVP)) {
|
||||||
if (++idledet_bads > 128) return 2; // remove detector
|
if (++idledet_bads > 128) return 2; // remove detector
|
||||||
return 1; // don't patch
|
return 1; // don't patch
|
||||||
|
|
|
@ -22,8 +22,8 @@ patch_desc_table:
|
||||||
.word (0x75f8<<16) | 0x67f8, 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 (0x75f6<<16) | 0x67f6, idle_detector_bcc8, idle_beq, Op6701 @ beq.s
|
||||||
.word (0x75f2<<16) | 0x67f2, 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 (0x7dfe<<16) | 0x60fe, idle_detector_bcc8, idle_bra, Op6001 @ bra.s
|
||||||
.word (0x7dfc<<16) | 0x60fc, idle_detector_dead, idle_bra, Op6001 @ bra.s
|
.word (0x7dfc<<16) | 0x60fc, idle_detector_bcc8, idle_bra, Op6001 @ bra.s
|
||||||
|
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
@ -90,10 +90,12 @@ cfi_loop:
|
||||||
|
|
||||||
|
|
||||||
.macro inc_counter cond
|
.macro inc_counter cond
|
||||||
@ ldr r0, =idle_hit_counter
|
@ ldr\cond r0, [r7, #0x60]
|
||||||
@ ldr r1, [r0]
|
@ mov r11,lr
|
||||||
@ add r1, r1, #1
|
@ sub r0, r4, r0
|
||||||
@ str\cond r1, [r0]
|
@ sub r0, r0, #2
|
||||||
|
@ bl\cond SekRegisterIdleHit
|
||||||
|
@ mov lr, r11
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
idle_bra:
|
idle_bra:
|
||||||
|
@ -139,43 +141,36 @@ idle_detector_bcc8:
|
||||||
and r2, r8, #0x00ff
|
and r2, r8, #0x00ff
|
||||||
orr r2, r2, #0x7100
|
orr r2, r2, #0x7100
|
||||||
orreq r2, r2, #0x0200
|
orreq r2, r2, #0x0200
|
||||||
tst r8, #0x0100 @ 67xx (beq)?
|
mov r0, r8, lsr #8
|
||||||
orrne r2, r2, #0x0400
|
cmp r0, #0x66
|
||||||
|
orrgt r2, r2, #0x0400 @ 67xx (beq)
|
||||||
|
orrlt r2, r2, #0x0c00 @ 60xx (bra)
|
||||||
|
|
||||||
@ r2 = patch_opcode
|
@ r2 = patch_opcode
|
||||||
sub r0, r4, #2
|
sub r0, r4, #2
|
||||||
ldrh r1, [r0]
|
ldrh r1, [r0]
|
||||||
mov r11,r2
|
mov r11,r2
|
||||||
|
mov r3, r7
|
||||||
bl SekRegisterIdlePatch
|
bl SekRegisterIdlePatch
|
||||||
cmp r0, #1 @ 0 - ok to patch, 1 - no patch, 2 - remove detector
|
cmp r0, #1 @ 0 - ok to patch, 1 - no patch, 2 - remove detector
|
||||||
strlth r11,[r4, #-2]
|
strlth r11,[r4, #-2]
|
||||||
ble exit_detector
|
ble exit_detector
|
||||||
|
|
||||||
@ remove detector from Cyclone
|
@ remove detector from Cyclone
|
||||||
tst r8, #0x0100 @ 67xx (beq)?
|
mov r0, r8, lsr #8
|
||||||
|
cmp r0, #0x66
|
||||||
|
ldrlt r1, =Op6001
|
||||||
ldreq r1, =Op6601
|
ldreq r1, =Op6601
|
||||||
ldrne r1, =Op6701
|
ldrgt r1, =Op6701
|
||||||
|
|
||||||
ldr r3, =CycloneJumpTab
|
ldr r3, =CycloneJumpTab
|
||||||
str r1, [r3, r8, lsl #2]
|
str r1, [r3, r8, lsl #2]
|
||||||
bx r1
|
bx r1
|
||||||
|
|
||||||
exit_detector:
|
exit_detector:
|
||||||
tst r8, #0x0100 @ 67xx (beq)?
|
mov r0, r8, lsr #8
|
||||||
|
cmp r0, #0x66
|
||||||
|
blt Op6001
|
||||||
beq Op6601
|
beq Op6601
|
||||||
b Op6701
|
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
|
|
||||||
|
|
||||||
|
|
|
@ -5041,8 +5041,8 @@ idle_install:
|
||||||
INSTALL_IDLE(0x75f8, 0x67f8, idle_detector_bcc8, 0x6701_idle, 0x6701);
|
INSTALL_IDLE(0x75f8, 0x67f8, idle_detector_bcc8, 0x6701_idle, 0x6701);
|
||||||
INSTALL_IDLE(0x75f6, 0x67f6, 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(0x75f2, 0x67f2, idle_detector_bcc8, 0x6701_idle, 0x6701);
|
||||||
INSTALL_IDLE(0x7dfe, 0x60fe, idle_detector_dead, 0x6001_idle, 0x6001);
|
INSTALL_IDLE(0x7dfe, 0x60fe, idle_detector_bcc8, 0x6001_idle, 0x6001);
|
||||||
INSTALL_IDLE(0x7dfc, 0x60fc, idle_detector_dead, 0x6001_idle, 0x6001);
|
INSTALL_IDLE(0x7dfc, 0x60fc, idle_detector_bcc8, 0x6001_idle, 0x6001);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
idle_remove:
|
idle_remove:
|
||||||
|
|
|
@ -40013,7 +40013,7 @@ RET(8)
|
||||||
|
|
||||||
|
|
||||||
extern int SekIsIdleCode(unsigned short *dst, int bytes);
|
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)
|
OPCODE(idle_detector_bcc8)
|
||||||
{
|
{
|
||||||
|
@ -40033,17 +40033,21 @@ OPCODE(idle_detector_bcc8)
|
||||||
newop = (Opcode & 0xfe) | 0x7100;
|
newop = (Opcode & 0xfe) | 0x7100;
|
||||||
if (!ret) newop |= 0x200;
|
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)
|
switch (ret)
|
||||||
{
|
{
|
||||||
case 0: PC[-1] = newop; break;
|
case 0: PC[-1] = newop; break;
|
||||||
case 1: 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:
|
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)
|
if (cond_true)
|
||||||
{
|
{
|
||||||
PC = dest_pc;
|
PC = dest_pc;
|
||||||
|
@ -40052,14 +40056,4 @@ end:
|
||||||
RET(8)
|
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
|
#endif // PICODRIVE_HACK
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue