Going though the code I noticed SDCC outputs the following sequence
ld a, i di push af
and then tests the P/O flag on exit
This is not actually permitted by the CPU errata documentation. It will work on a CMOS Z80 and most clones and emulators (although some emulators emulate the erratum correctly!) but on an NMOS Z80 will now and then randomly failure to restore the correct interrupt state.
NMOS Z80 requires a workaround (such as snooping below the stack bottom) to identify if an interrupt occurred
during the ld a,i/di sequence. See Z80 Family Questions and Answers on p131 (copy handily available at: http://z80.info/zip/ZilogProductSpecsDatabook129-143.pdf)
If we want to fix this, I think it's best to add a crt asm function (__sdcc_critical ?) to save IFF2 into both Acc and Carry or Zero and then disable interrupts. Then the caller can either assign (genCritical) or push the result. And after a POP AF a simple JR NC/NZ suffices to skip the EI instead of JP PO.
Fixed in [r11797]. New Z80 port option: --nmos-z80 generates workaround.