From d6d1f687a8f2bcdeeaa2221423e9800448efac29 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 19 Dec 2012 07:38:35 -0800 Subject: [PATCH] Make the intr handler public, will need for timers. The idea here is that alarm/vtimers/etc. can implement a subclass to pass more arguments / do whatever they need to. --- Core/HLE/sceKernelInterrupt.cpp | 152 +++++++++++++++----------------- Core/HLE/sceKernelInterrupt.h | 35 ++++++++ 2 files changed, 104 insertions(+), 83 deletions(-) diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 7d38ff6802..bc335bbf04 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -35,9 +35,9 @@ struct Interrupt // Yeah, this bit is a bit silly. static int interruptsEnabled = 1; - static bool inInterrupt; + void __InterruptsInit() { interruptsEnabled = 1; @@ -127,74 +127,19 @@ bool __CanExecuteInterrupt() return !inInterrupt; } -class AllegrexInterruptHandler; - -struct PendingInterrupt { - AllegrexInterruptHandler *handler; - int arg; - bool hasArg; -}; - - -class AllegrexInterruptHandler -{ -public: - virtual ~AllegrexInterruptHandler() {} - virtual void copyArgsToCPU(const PendingInterrupt &pend) = 0; - virtual void queueUp() = 0; - virtual void queueUpWithArg(int arg) = 0; -}; - -std::list pendingInterrupts; - -class SubIntrHandler : public AllegrexInterruptHandler -{ -public: - SubIntrHandler() {} - virtual void queueUp() - { - if (!enabled) - return; - PendingInterrupt pend; - pend.handler = this; - pend.hasArg = false; - pendingInterrupts.push_back(pend); - } - virtual void queueUpWithArg(int arg) - { - if (!enabled) - return; - PendingInterrupt pend; - pend.handler = this; - pend.arg = arg; - pend.hasArg = true; - pendingInterrupts.push_back(pend); - } - - virtual void copyArgsToCPU(const PendingInterrupt &pend) - { - DEBUG_LOG(CPU, "Entering interrupt handler %08x", handlerAddress); - currentMIPS->pc = handlerAddress; - currentMIPS->r[MIPS_REG_A0] = pend.hasArg ? pend.arg : number; - currentMIPS->r[MIPS_REG_A1] = handlerArg; - // RA is already taken care of - } - - bool enabled; - int number; - u32 handlerAddress; - u32 handlerArg; -}; - class IntrHandler { public: - void add(int subIntrNum, SubIntrHandler handler) + void add(int subIntrNum, SubIntrHandler *handler) { subIntrHandlers[subIntrNum] = handler; } void remove(int subIntrNum) { - subIntrHandlers.erase(subIntrNum); + if (has(subIntrNum)) + { + delete subIntrHandlers[subIntrNum]; + subIntrHandlers.erase(subIntrNum); + } } bool has(int subIntrNum) const { @@ -203,7 +148,7 @@ public: SubIntrHandler *get(int subIntrNum) { if (has(subIntrNum)) - return &subIntrHandlers[subIntrNum]; + return subIntrHandlers[subIntrNum]; else return 0; // what to do, what to do... @@ -213,10 +158,10 @@ public: { // Just call execute on all the subintr handlers for this interrupt. // They will get queued up. - for (std::map::iterator iter = subIntrHandlers.begin(); iter != subIntrHandlers.end(); ++iter) + for (std::map::iterator iter = subIntrHandlers.begin(); iter != subIntrHandlers.end(); ++iter) { if (subintr == -1 || iter->first == subintr) - iter->second.queueUp(); + iter->second->queueUp(); } } @@ -224,18 +169,17 @@ public: { // Just call execute on all the subintr handlers for this interrupt. // They will get queued up. - for (std::map::iterator iter = subIntrHandlers.begin(); iter != subIntrHandlers.end(); ++iter) + for (std::map::iterator iter = subIntrHandlers.begin(); iter != subIntrHandlers.end(); ++iter) { if (subintr == -1 || iter->first == subintr) - iter->second.queueUpWithArg(arg); + iter->second->queueUpWithArg(arg); } } private: - std::map subIntrHandlers; + std::map subIntrHandlers; }; - class InterruptState { public: @@ -261,11 +205,43 @@ public: InterruptState intState; IntrHandler intrHandlers[PSP_NUMBER_INTERRUPTS]; +std::list pendingInterrupts; + // http://forums.ps2dev.org/viewtopic.php?t=5687 // http://www.google.se/url?sa=t&rct=j&q=&esrc=s&source=web&cd=7&ved=0CFYQFjAG&url=http%3A%2F%2Fdev.psnpt.com%2Fredmine%2Fprojects%2Fuofw%2Frepository%2Frevisions%2F65%2Fraw%2Ftrunk%2Finclude%2Finterruptman.h&ei=J4pCUKvyK4nl4QSu-YC4Cg&usg=AFQjCNFxJcgzQnv6dK7aiQlht_BM9grfQQ&sig2=GGk5QUEWI6qouYDoyE07YQ +void SubIntrHandler::queueUp() +{ + if (!enabled) + return; + PendingInterrupt pend; + pend.handler = this; + pend.hasArg = false; + pendingInterrupts.push_back(pend); +}; + +void SubIntrHandler::queueUpWithArg(int arg) +{ + if (!enabled) + return; + PendingInterrupt pend; + pend.handler = this; + pend.arg = arg; + pend.hasArg = true; + pendingInterrupts.push_back(pend); +} + +void SubIntrHandler::copyArgsToCPU(const PendingInterrupt &pend) +{ + DEBUG_LOG(CPU, "Entering interrupt handler %08x", handlerAddress); + currentMIPS->pc = handlerAddress; + currentMIPS->r[MIPS_REG_A0] = pend.hasArg ? pend.arg : number; + currentMIPS->r[MIPS_REG_A1] = handlerArg; + // RA is already taken care of +} + // Returns true if anything was executed. bool __RunOnePendingInterrupt() @@ -331,6 +307,24 @@ void __KernelReturnFromInterrupt() } } +u32 __RegisterSubInterruptHandler(u32 intrNumber, u32 subIntrNumber, SubIntrHandler *subIntrHandler) +{ + subIntrHandler->number = subIntrNumber; + intrHandlers[intrNumber].add(subIntrNumber, subIntrHandler); + return 0; +} + +u32 __ReleaseSubInterruptHandler(u32 intrNumber, u32 subIntrNumber) +{ + if (!intrHandlers[intrNumber].has(subIntrNumber)) + return -1; + + // TODO: should check if it's pending and remove it from pending list! (although that's probably unlikely) + + intrHandlers[intrNumber].remove(subIntrNumber); + return 0; +} + u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg) { DEBUG_LOG(HLE,"sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x)", intrNumber, subIntrNumber, handler, handlerArg); @@ -338,29 +332,21 @@ u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handl if (intrNumber >= PSP_NUMBER_INTERRUPTS) return -1; - SubIntrHandler subIntrHandler; - subIntrHandler.number = subIntrNumber; - subIntrHandler.enabled = false; - subIntrHandler.handlerAddress = handler; - subIntrHandler.handlerArg = handlerArg; - intrHandlers[intrNumber].add(subIntrNumber, subIntrHandler); - return 0; + SubIntrHandler *subIntrHandler = new SubIntrHandler(); + subIntrHandler->enabled = false; + subIntrHandler->handlerAddress = handler; + subIntrHandler->handlerArg = handlerArg; + return __RegisterSubInterruptHandler(intrNumber, subIntrNumber, subIntrHandler); } u32 sceKernelReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber) { DEBUG_LOG(HLE,"sceKernelReleaseSubIntrHandler(%i, %i)", PARAM(0), PARAM(1)); - // TODO: should check if it's pending and remove it from pending list! (although that's probably unlikely) - if (intrNumber >= PSP_NUMBER_INTERRUPTS) return -1; - if (!intrHandlers[intrNumber].has(subIntrNumber)) - return -1; - - intrHandlers[intrNumber].remove(subIntrNumber); - return 0; + return __ReleaseSubInterruptHandler(intrNumber, subIntrNumber); } u32 sceKernelEnableSubIntr(u32 intrNumber, u32 subIntrNumber) diff --git a/Core/HLE/sceKernelInterrupt.h b/Core/HLE/sceKernelInterrupt.h index adc13e5bcd..87228f4d55 100644 --- a/Core/HLE/sceKernelInterrupt.h +++ b/Core/HLE/sceKernelInterrupt.h @@ -54,6 +54,38 @@ enum PSPGeSubInterrupts { PSP_GE_SUBINTR_SIGNAL = 15 }; +class AllegrexInterruptHandler; + +struct PendingInterrupt { + AllegrexInterruptHandler *handler; + int arg; + bool hasArg; +}; + + +class AllegrexInterruptHandler +{ +public: + virtual ~AllegrexInterruptHandler() {} + virtual void copyArgsToCPU(const PendingInterrupt &pend) = 0; + virtual void queueUp() = 0; + virtual void queueUpWithArg(int arg) = 0; +}; + +class SubIntrHandler : public AllegrexInterruptHandler +{ +public: + SubIntrHandler() {} + virtual void queueUp(); + virtual void queueUpWithArg(int arg); + virtual void copyArgsToCPU(const PendingInterrupt &pend); + + bool enabled; + int number; + u32 handlerAddress; + u32 handlerArg; +}; + bool __IsInInterrupt(); void __InterruptsInit(); void __InterruptsShutdown(); @@ -62,6 +94,9 @@ void __TriggerInterruptWithArg(PSPInterrupt intno, int subintr, int arg); // Fo bool __RunOnePendingInterrupt(); void __KernelReturnFromInterrupt(); +u32 __RegisterSubInterruptHandler(u32 intrNumber, u32 subIntrNumber, SubIntrHandler *subIntrHandler); +u32 __ReleaseSubInterruptHandler(u32 intrNumber, u32 subIntrNumber); + u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg); u32 sceKernelReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber); u32 sceKernelEnableSubIntr(u32 intrNumber, u32 subIntrNumber);