As detailed in the Undocumented Z80, the RETI instruction copies iff2 to iff1, which is the same behaviour as RETN. This isn't mentioned in the official documentation.
I've just tested it on real hardware and can confirm it does restore iff1 from iff2. My test code was as follows:
8000 JR 8000
8002 HALT
8003 DI
8004 LD A,04
8006 OUT (FE),A
8008 HALT
0038 LD B,06
003A DJNZ 003A
003C EI
003D RET
0066 LD HL,8002
0069 PUSH HL
006A LD A,02
006C OUT (FE),A
006E RETI
It starts with a tight loop with interrupts enabled. The maskable interrupt handler delays long enough for the interrupt to become inactive, then returns. Triggering an NMI sets the border red and uses RETI to restore iff1 and return to a HALT. If interrupts are disabled at this point the border remains red and the CPU is halted. If iff1 is restored to the previous enabled state the HALT waits for the next frame interrupt then continues to set the border green, before halting.
Tests show that both RETI and RETN give the same behaviour on real hardware, with the border turning green. In the emulator RETN works as expected but the border remains red with RETI because iff1 wasn't restored.
The on_reti handler could probably just call on_retn instead of on_return. Though it uses handlers that mention 'retn' (such as set_iff1_on_retn) so it might be better to have separate 'reti' versions?
As detailed in the Undocumented Z80, the
RETI
instruction copies iff2 to iff1, which is the same behaviour asRETN
. This isn't mentioned in the official documentation.I've just tested it on real hardware and can confirm it does restore iff1 from iff2. My test code was as follows:
It starts with a tight loop with interrupts enabled. The maskable interrupt handler delays long enough for the interrupt to become inactive, then returns. Triggering an NMI sets the border red and uses
RETI
to restore iff1 and return to aHALT
. If interrupts are disabled at this point the border remains red and the CPU is halted. If iff1 is restored to the previous enabled state the HALT waits for the next frame interrupt then continues to set the border green, before halting.Tests show that both
RETI
andRETN
give the same behaviour on real hardware, with the border turning green. In the emulatorRETN
works as expected but the border remains red withRETI
because iff1 wasn't restored.The
on_reti
handler could probably just callon_retn
instead ofon_return
. Though it uses handlers that mention 'retn' (such asset_iff1_on_retn
) so it might be better to have separate 'reti' versions?