diff --git a/src/gba/gba-memory.c b/src/gba/gba-memory.c index d5848cb89..9722d5309 100644 --- a/src/gba/gba-memory.c +++ b/src/gba/gba-memory.c @@ -14,6 +14,8 @@ #include "hle-bios.h" #include "util/memory.h" +#define IDLE_LOOP_THRESHOLD 200 + static uint32_t _popcount32(unsigned bits); static uint32_t _deadbeef[2] = { 0xDEADBEEF, 0xFEEDFACE }; @@ -175,6 +177,7 @@ static void _analyzeForIdleLoop(struct GBA* gba, struct ARMCore* cpu, uint32_t a case ARM_BRANCH: if ((uint32_t) info.op1.immediate + nextAddress + WORD_SIZE_THUMB * 2 == address) { gba->idleLoop = address; + gba->idleOptimization = IDLE_LOOP_REMOVE; } gba->idleDetectionStep = -1; return; @@ -206,6 +209,10 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { case 1: if (memcmp(gba->cachedRegisters, cpu->gprs, sizeof(gba->cachedRegisters))) { gba->idleDetectionStep = -1; + ++gba->idleDetectionFailures; + if (gba->idleDetectionFailures > IDLE_LOOP_THRESHOLD) { + gba->idleOptimization = IDLE_LOOP_IGNORE; + } break; } _analyzeForIdleLoop(gba, cpu, address); diff --git a/src/gba/gba.c b/src/gba/gba.c index befa19e1d..4ee826a67 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -79,6 +79,7 @@ static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component) { gba->idleLoop = -1; gba->lastJump = 0; gba->idleDetectionStep = 0; + gba->idleDetectionFailures = 0; } void GBADestroy(struct GBA* gba) { diff --git a/src/gba/gba.h b/src/gba/gba.h index b806e98e6..0bd9b222f 100644 --- a/src/gba/gba.h +++ b/src/gba/gba.h @@ -145,6 +145,7 @@ struct GBA { uint32_t idleLoop; uint32_t lastJump; int idleDetectionStep; + int idleDetectionFailures; int32_t cachedRegisters[16]; bool taintedRegisters[16]; };