I reported the bug just now. It’s at  https://sourceforge.net/p/sdcc/bugs/2416/ .

Now I have to figure out how to handle critical sections.

For now, just two functions–di() and ei(). They will use a global variable uint8_t interruptDisableReferenceCount. If it’s 0, interrupts are enabled. It will initialize to 1.

I also dealt with the __interrupt bug where it doesn’t generate ei before reti.

Here is my interrupt.c file for now:

  1 #include "tick.h"
  2 #include "uart.h"
  3 #include "membank.h"
  4 
  5 /*
  6 ; for crt0.s
  7 .globl _do_RST_00H
  8 .globl _do_RST_08H
  9 .globl _do_RST_10H
 10 .globl _do_RST_01H
 11 .globl _do_RST_20H
 12 .globl _do_RST_28H
 13 .globl _do_RST_30H
 14 .globl _do_RST_38H
 15 .globl _do_NMI
 16 */
 17 
 18 uint8_t interruptDisableRefCount = 1;
 19 
 20 void do_RST_00H() 
 21 {
 22 }
 23 
 24 void do_RST_08H()
 25 {
 26 }
 27 
 28 void do_RST_10H()
 29 {
 30 }
 31 
 32 void do_RST_18H()
 33 {
 34 }
 35 
 36 void do_RST_20H()
 37 {
 38 }
 39 
 40 void do_RST_28H()
 41 {
 42 }
 43 
 44 void do_RST_30H()
 45 {
 46 }
 47 
 48 // Has to be naked because __interrupt fails to generate the ei before the reti
 49 void do_RST_38H() __naked
 50 {
 51     __asm__("push af");
 52     __asm__("push bc");
 53     __asm__("push de");
 54     __asm__("push hl");
 55     __asm__("push ix");
 56     __asm__("push iy");
 57 
 58 #ifdef INT_SAVE_ALT_REG
 59     __asm__("exx");
 60     __asm__("push af");
 61     __asm__("push bc");
 62     __asm__("push de");
 63     __asm__("push hl");
 64     __asm__("push ix");
 65     __asm__("push iy");
 66 #endif
 67 
 68     //tickISR();
 69     uartISR();
 70 
 71 #ifdef INT_SAVE_ALT_REG
 72     __asm__("pop iy");
 73     __asm__("pop ix");
 74     __asm__("pop hl");
 75     __asm__("pop de");
 76     __asm__("pop bc");
 77     __asm__("pop af");
 78     __asm__("exx");
 79 #endif
 80 
 81     __asm__("pop iy");
 82     __asm__("pop ix");
 83     __asm__("pop hl");
 84     __asm__("pop de");
 85     __asm__("pop bc");
 86     __asm__("pop af");
 87     __asm__("ei");
 88     __asm__("reti");
 89 }
 90 
 91 void do_NMI() __interrupt __critical
 92 {
 93     //nmiISR();
 94 }
 95 
 96 void di() __naked
 97 {
 98     __asm__("push af");
 99     __asm__("ld a, (_interruptDisableRefCount)");
100     __asm__("or a");
101     __asm__("jr nz, skip_di");
102     __asm__("di");
103     __asm__("skip_di:");
104     __asm__("inc a");
105     __asm__("ld (_interruptDisableRefCount), a");
106     __asm__("pop af");
107     __asm__("ret");
108 }
109 
110 void ei() __naked
111 {
112     __asm__("push af");
113     __asm__("ld a, (_interruptDisableRefCount)");
114     __asm__("dec a");
115     __asm__("ld (_interruptDisableRefCount), a");
116     __asm__("or a");
117     __asm__("jr nz, skip_ei");
118     __asm__("pop af");
119     __asm__("ret");
120     __asm__("skip_ei:");
121     __asm__("pop af");
122     __asm__("ei");
123     __asm__("ret");
124 }

I have also purged __critical from my code and placed di() and ei() where I need it.