So for context I would like to let you know what I understand so far:
Interupt Handling is called after an instruction execution and Interrupt Master Enable flag is set.
Interupt Handling is comprised of serveral "interrupt routines" (for gameboy, it has Vblank, LCD stat, timer, joypad, and serial).
CPU needs to handle each interupt depending on values set on IE flag and IF flag.
Interupt routines has priorities (not really related to my question).
Interrupt routines must have start and end
So looking into interupt routines, it starts with pushing registers values that should be retained after the routine ends into the stack pointer. Now it always has reti instruction which I think is always the end of an interupt routine which should pop the address of the next instruction before the interupt was handled.
I would like to know if:
is it a "standard" that reti instruction should appear only once each interupt routine and appears only at the end? because that's the only way I could determine if I would end reading further instruction,
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,
before the start of an interupt handling, I need to explicitly push the address of the next instruction into the stack pointer, since there is no assembly instruction indicating of pushing it before the start of interupt handling. This is for reti intruction btw at the end of an interupt.
EDIT:
So to give more context about my problem I decided to post my instruction cycle code.
in 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)
}