We could take a simple stage model like ARM Cortex-M3 , ie 3 stages model : Fetch, Decode and Execute.
On Fetch stage :
- Checks if there is a interrupt. If there are enabled and there is a interrupt handler for it, the CPU accepts it, initiating the interrupt sequence.
- Reads 4 bytes from RAM
- Increase PC by 4.
On Decode stage :
- Decode instruction fetched on previus stage.
- If the instruction have a long immediate value (M & L bits are 1)
- Fetch next 4 bytes (32 bit immediate value)
- Increase PC by 4
- Sets input/output registers
Execute stage, well... executes it and writes to the output. If is a JMP or CALL instruction, obviously would overwrite PC register value.
Interrupt checking is doing on Fetch stage, before anything.
If malicious code can just turn off interrupts, why do you need to have arbitrary if chain limits?