As I know it probably does not have any effect on the IRQ routine. Or does it?
It does indeed: It allows other IRQs to be serviced. The 6502 I flag "masks" IRQs, and it is set automatically as soon as an IRQ is serviced and cleared implicitly by RTI
. So, normally, IRQs are only ever serviced sequentially. By clearing the I flag yourself in an ISR (interrupt service routine), you actively allow this routine to be interrupted by serving a different IRQ.
The code you show here is special, containing a bunch of NOP
s after the CLI
. This is typically done for (almost) cycle-exact timing of the code in an ISR, normally for an IRQ requested by the VIC graphics chip. To fully understand how this works, here's some in-depth information on 6502 IRQ handling (still not complete):
An IRQ is signaled to the 6502 by pulling down the IRQ line to low level. This low level is kept until the IRQ is serviced, which needs some assistence from the code in the ISR. With multiple IRQ sources, it's first necessary to check which one requested the ISR, then acknowledge the IRQ there, so this chip stops pulling down the IRQ line. When coding graphical effects on the C64, you often only enable a single IRQ source, so checking isn't necessary any more -- just acknowledge the IRQ at the VIC and it will stop pulling the line.
Now, the 6502 also has an internal flag for "IRQ requested". During execution of an instruction, typically right before the last cycle (but that's different for a few instructions), the CPU checks the state of the IRQ line, and if it is low, the internal flag gets set. Right after each instruction, this internal flag is checked, and, if set (while the I flag is unset), servicing an IRQ is started instead of executing the next instruction.
So, the exact time when the CPU starts servicing an IRQ can vary quite a few cycles (the difference between max and min cycles for executing an instruction, plus one extra as there are instructions checking the IRQ line before the second last cycle), which is unacceptable for many graphical effects. One strategy for achieving exact timing is to have the IRQ occur while the CPU does something we know: execute a bunch of NOP
s. They take 2 cycles each, so the exact time of servicing the IRQ can only vary by one cycle. This last cycle can be accounted for using another trick not relevant for this question.
Code using this trick typically restores the stackpointer in the second ISR, so the stack looks like only one ISR was called by the CPU. Therefore, a simple RTI
in the second ISR will return to the main code.