确定 Gameboy GB 仿真的中断例程何时结束

Determining when an Interrupt Routine will end for Gameboy GB Emulation

所以对于上下文,我想让你知道我到目前为止的理解:

所以查看中断例程,首先是将例程结束后应保留的寄存器值压入堆栈指针。现在它总是有 reti 指令,我认为它是 always 中断例程的结尾,它应该在处理中断之前弹出下一条指令的地址。

我想知道是否:

编辑:

因此,为了提供有关我的问题的更多背景信息,我决定 post 我的指令周期代码。

在CPU.c

#include "InteruptHandler.c"
void main(){
    while(){ //No proper argument yet. for fetch-decode-execute cycle
    opcode = fetchInstruction();
    decodeandExecuteInstruction(opcode); //Lets say an instruction is executed and it enabled the IME_flag. that is IME_flag = ENABLED

    //Check if ime_flag is enabled. processInterupt if true.
    isInteruptEnabled() ? processInterupts(): 0; //This would fall true.
    }
}

在InteruptHandler.c

processInterupts(){

    opcode;
    bitmask = 0x01;

    //Check each bit for interupt. Bitmask will go 0x00 if the value 0x80 is shifted by 1
    for(; bitmask ; bitmask = bitmask << 1){

        //CHeck if IE and IF flag for corresponding interupt is set. process interupt if set
        IE_flag & bitmask ? (IF_flag & bitmask ? determineInterupt(bitmask) : 0) : 0; 
    }
}

determineInterupt(bitmask){

    //push the next instruction address to stack pointer
    push(PC);

    //Set PC into corresponding interupt address

//code below is my problem. I stumbled upon how would I end this function and I came up to determining when an interupt routine ends. 
//I came up with the reti function. 
//But after realizing that I already set the PC somewhere above this code, I just need to discard this code and let the main function do its instruction cycling. 
//Thanks to @duskwuff for pointing that out. 
//I just added some code to end the bitmask checking when it sees 1 interupt request and is most priotiry. 
//Also thanks to @Ped7g for giving me more information about the complexity of interupt handling. I'm not yet seeing where I should implement those. There are still so many thing to implement and yet to know when this excatly can happen.
//My question has been answered nevertheless, which is to end a function code blocks that I discarded at the end :)

//process the corresponding interupt
    do{
        opcode = fetchInstruction();
        decodeandexecuteInstruction(opcode);
    }while (opcode != RETI)
}
  • Interrupt routines must have start and end

这不是真的。您不应该对内存中的代码布局做出任何假设 - 只是 运行 您遇到的指令。

在某些情况下,中断服务例程可以在返回之前重新启用中断,以允许同时处理另一个中断。您的设计应该考虑到这一点。

it uses reti instead of ret because we want to assert that ime flag is still enabled and thus can continue checking if any other interupt needs to be served,

没有。 RETI 指令在返回时重新启用中断——它实际上是 EI 和 RET 的组合。没有涉及断言。