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



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

  • 在执行指令并设置中断主启用标志后调用中断主处理。

  • Interupt Handling由服务器"中断例程"组成(对于gameboy,它具有Vblank,LCD统计,计时器,游戏手柄和串行(。

  • CPU 需要根据 IE 标志和 IF 标志上设置的值处理每个中断。

  • Interupt 例程有优先级(与我的问题无关(。

  • 中断例程必须具有开始和结束

因此,查看间歇例程,它首先将例程结束后应保留的寄存器值推送到堆栈指针中。现在它总是有 reti 指令,我认为它总是一个中断例程的结束,它应该在处理中断之前弹出下一条指令的地址。

我想知道是否:

  • RETI 指令在每个中断例程中只出现一次并且出现在最后,这是否是一种"标准"? 因为这是我确定是否要结束阅读进一步说明的唯一方法,

  • 它使用 RETI 而不是 RET,因为我们想断言 IME 标志仍然启用,因此可以继续检查是否需要提供任何其他中断,

  • 在 interupt 处理开始之前,我需要显式地将下一条指令的地址推送到堆栈指针中,因为在 interupt 处理开始之前没有程序集指令指示推送它。这是在中断结束时的重新入侵。

编辑:

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

在 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.
}
}

In 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)
}
  • 中断例程必须有开始和结束

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

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

它使用 RETI 而不是 RET,因为我们想断言 IME 标志仍然启用,因此可以继续检查是否需要提供任何其他中断,

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

最新更新