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

时间:2017-07-11 01:49:40

标签: c assembly emulation gameboy

因此,对于上下文,我想告诉您到目前为止我所理解的内容:

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

  • Interupt Handling由多个"中断例程"组成。 (对于gameboy,它有Vblank,LCD stat,计时器,游戏手柄和连续剧)。

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

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

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

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

我想知道是否:

  • 是"标准" reti指令应该只出现一次每个中断例程,并且最后只显示 ?因为这是我决定是否结束阅读进一步教学的唯一方法,

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

  • 在中断处理开始之前,我需要显式地将下一条指令的地址压入堆栈指针,因为没有汇编指令指示在中断处理开始之前推送它。这是在中断结束时的reti intruction btw。

编辑:

因此,为了提供有关我的问题的更多上下文,我决定发布我的指令循环代码。

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

1 个答案:

答案 0 :(得分:2)

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

事实并非如此。你不应该对内存中的代码布局做任何假设 - 只需运行你遇到的指令。

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

  

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

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