Attempt to reenable and fix irq yielding

This commit is contained in:
Gericom 2025-05-30 17:50:12 +02:00
parent 2414cf9d80
commit d6086d4539
6 changed files with 103 additions and 34 deletions

View File

@ -57,7 +57,7 @@ INCLUDES := include source ../common ../../libs/mini-printf
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -marm -mthumb-interwork -march=armv5te -mtune=arm946e-s \
-DLIBTWL_ARM9 -DARM9 #-DGBAR3_IRQ_YIELDING
-DLIBTWL_ARM9 -DARM9 -DGBAR3_IRQ_YIELDING
CFLAGS := -g -Wall -O2\
-fomit-frame-pointer\

View File

@ -29,42 +29,65 @@ u32 fs_waitForCompletion(FsWaitToken* waitToken, bool keepIrqsDisabled)
{
u32 irqs;
#ifdef GBAR3_IRQ_YIELDING
irqs = arm_disableIrqs();
#endif
while (true)
if (gIrqYieldingEnabled)
{
#ifndef GBAR3_IRQ_YIELDING
irqs = arm_disableIrqs();
#endif
if (waitToken && waitToken->transactionComplete)
vm_disableIrqYielding();
while (true)
{
break;
if (waitToken && waitToken->transactionComplete)
{
break;
}
FsWaitToken* currentWaitToken = sCurrentWaitToken;
if (!currentWaitToken)
{
break;
}
else if (isArm7FsOperationComplete())
{
currentWaitToken->transactionComplete = true;
sCurrentWaitToken = nullptr;
break;
}
if (!(irqs & 0x80) && !vm_yieldGbaIrqs())
{
arm_restoreIrqs(irqs);
irqs = arm_disableIrqs();
}
}
FsWaitToken* currentWaitToken = sCurrentWaitToken;
if (!currentWaitToken)
{
break;
}
else if (isArm7FsOperationComplete())
{
currentWaitToken->transactionComplete = true;
sCurrentWaitToken = nullptr;
break;
}
#ifdef GBAR3_IRQ_YIELDING
if (!(irqs & 0x80) && !vm_yieldGbaIrqs())
{
arm_restoreIrqs(irqs);
irqs = arm_disableIrqs();
}
#else
arm_restoreIrqs(irqs);
#endif
vm_restoreIrqYielding(true);
}
else
#endif
{
while (true)
{
irqs = arm_disableIrqs();
if (waitToken && waitToken->transactionComplete)
{
break;
}
FsWaitToken* currentWaitToken = sCurrentWaitToken;
if (!currentWaitToken)
{
break;
}
else if (isArm7FsOperationComplete())
{
currentWaitToken->transactionComplete = true;
sCurrentWaitToken = nullptr;
break;
}
arm_restoreIrqs(irqs);
}
}
if (!keepIrqsDisabled)
{
arm_restoreIrqs(irqs);
}
return irqs;
}

View File

@ -489,7 +489,7 @@ ITCM_CODE static void dmaStartImmediate(int channel, GbaDmaChannel* dmaIoBase, u
src = src + ROM_LINEAR_GBA_ADDRESS - ROM_LINEAR_DS_ADDRESS;
}
u32 dst = dmaIoBase->dst;
triggerDmaIrqIfEnabled(channel, control);
bool irqYieldingState = vm_disableIrqYielding();
if (channel == 3)
{
vm_enableNestedIrqs();
@ -516,6 +516,8 @@ ITCM_CODE static void dmaStartImmediate(int channel, GbaDmaChannel* dmaIoBase, u
{
vm_disableNestedIrqs();
}
triggerDmaIrqIfEnabled(channel, control);
vm_restoreIrqYielding(irqYieldingState);
}
ITCM_CODE static void dmaStart(int channel, GbaDmaChannel* dmaIoBase, u32 control)

View File

@ -29,7 +29,8 @@ static u16 sCacheBlockToRomBlock[SDC_BLOCK_COUNT];
/// total number of cache blocks when some blocks are permanently loaded.
static u32 sBlockCount;
static u32 sTabuBlock;
static u32 sTabuLevel;
static u32 sTabuBlocks[2];
vu32 gSdCacheIrqForbiddenRomBlockReplacementRange;
static DWORD sClusterTable[512];
@ -43,12 +44,25 @@ static u32 getBlockToReplace(void)
{
sRandomState = sRandomState * 1566083941u + 2531011u;
u32 maxPlusOne = sBlockCount;
if (sTabuBlock != SDC_BLOCK_INVALID)
if (sTabuBlocks[0] != SDC_BLOCK_INVALID)
{
maxPlusOne--;
}
if (sTabuLevel > 0 && sTabuBlocks[1] != SDC_BLOCK_INVALID)
{
maxPlusOne--;
}
u32 block = ((sRandomState >> 16) * maxPlusOne) >> 16;
return block == sTabuBlock ? (sBlockCount - 1) : block;
if (block == sTabuBlocks[0])
{
block = maxPlusOne;
}
else if (sTabuLevel > 0 && block == sTabuBlocks[1])
{
block = maxPlusOne + 1;
}
return block;
}
static bool isCurrentlyFetching(void)
@ -178,9 +192,11 @@ static void* loadRomBlock(u32 romBlock, u32 cacheBlock)
sCurrentFetch.cacheBlock = cacheBlock;
}
if ((arm_getCpsr() & 0x1F) != 0x12)
bool decreaseTabuLevel = false;
if ((arm_getCpsr() & 0x1F) != 0x12 && sTabuLevel < 2)
{
sTabuBlock = cacheBlock;
sTabuBlocks[sTabuLevel++] = cacheBlock;
decreaseTabuLevel = true;
}
arm_restoreIrqs(irqs);
@ -198,6 +214,11 @@ static void* loadRomBlock(u32 romBlock, u32 cacheBlock)
fillOutOfBoundsCacheBlock(romBlock, cacheBlock);
}
if (decreaseTabuLevel)
{
sTabuLevel--;
}
return &sdc_cache[cacheBlock][0];
}
@ -248,6 +269,10 @@ void sdc_init(void)
sCurrentFetch.cacheBlock = SDC_BLOCK_INVALID;
sCurrentFetch.romBlock = SDC_ROM_BLOCK_INVALID;
gSdCacheIrqForbiddenRomBlockReplacementRange = 0;
sTabuLevel = 0;
sTabuBlocks[0] = SDC_BLOCK_INVALID;
sTabuBlocks[1] = SDC_BLOCK_INVALID;
gIrqYieldingEnabled = true;
sClusterTable[0] = sizeof(sClusterTable) / sizeof(DWORD);
gFile.cltbl = sClusterTable;

View File

@ -4,9 +4,13 @@
extern "C" {
#endif
extern u32 gIrqYieldingEnabled;
extern void vm_enableNestedIrqs(void);
extern void vm_disableNestedIrqs(void);
extern bool vm_yieldGbaIrqs(void);
extern bool vm_disableIrqYielding(void);
extern void vm_restoreIrqYielding(bool isIrqYieldingEnabled);
#ifdef __cplusplus
}

View File

@ -7,6 +7,10 @@
#define IRQ_RETURN_FOR_NESTED_IRQ_ENABLE 0xE2 // always condition for subs pc, r13, #4
#define IRQ_RETURN_FOR_NESTED_IRQ_DISABLE 0x92 // LS condition for sublss pc, r13, #4
.global gIrqYieldingEnabled
gIrqYieldingEnabled:
.word 0
nestedIrqLevel:
.word 0
@ -52,6 +56,17 @@ arm_func vm_disableNestedIrqs
yieldGbaIrqsGbaMode:
swi 0x7F0000 // swiVMReturnFromYield
arm_func vm_disableIrqYielding
mov r1, #0
adr r2, gIrqYieldingEnabled
swp r0, r1, [r2]
bx lr
arm_func vm_restoreIrqYielding
adr r1, gIrqYieldingEnabled
str r0, [r1]
bx lr
.section ".itcm", "ax"
arm_func vm_yieldGbaIrqs