Saving compiler temporary variables

The COP8_ISR library simplifies the creation of interrupt handlers. Including cop8_isr.h gives a program access to the SaveContext() and RestoreContext() macros.

Some operations require the use of temporary variables to store intermediate values. Since main line code and interrupt code are independent, a conflict can arise if the compiler uses the same temporary variable in both the main loop and in the interrupt. Use the SaveContext() and RestoreContext() macros at the beginning and end of interrupt subroutines to ensure registers and temporary variables are not overwritten.

Figure 4-2. interrupt subroutine using SaveContext() and RestoreContext() rtccint2.lst

0008                                unsigned long rtcc_total;
01FE 02 00                          void __SWI(void)
0200                                {
                                            SaveContext();
0200 67        PUSHA
0201 9D FE     LD     A,B
0203 67        PUSHA
0204 9D EF     LD     A,0EF
0206 67        PUSHA
0207 9D F0     LD     A,0F0
0209 67        PUSHA
020A 9D FF     LD     A,S
020C 67        PUSHA
020D 9D FC     LD     A,X
020F 67        PUSHA
0210 DF 00     LD     S,#000
0212 5F        LD     B,#00
0213 AA        LD     A,[B+]
0214 67        PUSHA
0215 48 FC     IFBNE  08

000A                                        unsigned long interrupt_count;
0217 9D A4     LD     A,0A4                 interrupt_count=PORTBD&0xf;
0219 DF 00     LD     S,#000
021B BC 0B 00  LD     000B,#00
021E 55        LD     B,#0A
021F A2        X      A,[B+]
0220 CE        DRSZ   B
0221 AE        LD     A,[B]
0222 95 0F     AND    A,#00F
0224 A2        X      A,[B+]
0225 9A 00     LD     [B+],#000
0227 55        LD     B,#0A                 interrupt_count++;
0228 A0        RC 
0229 AE        LD     A,[B]
022A 90 01     ADC    A,#001
022C A2        X      A,[B+]
022D 64        CLRA
022E 80        ADC    A,[B]

                                                                                                                                              /*_figure a_*/
022F A6        X      A,[B]                 rtcc_total += interrupt_count+0x8000;
0230 A0        RC 
0231 64        CLRA
0232 55        LD     B,#0A
0233 80        ADC    A,[B]
0234 9C 02     X      A,0002
0236 9D 0B     LD     A,000B
0238 90 80     ADC    A,#080
023A 9C 03     X      A,0003
023C A0        RC 
023D 9D 02     LD     A,0002
023F 57        LD     B,#08
0240 80        ADC    A,[B]
0241 A6        X      A,[B]
0242 9D 03     LD     A,0003
0244 56        LD     B,#09
0245 80        ADC    A,[B]
                                                                                                                                              /*_figure a_*/


0246 A6        X      A,[B]                 RestoreContext();
0247 DF 00     LD     S,#000
0249 58        LD     B,#07
024A 8C        POPA
024B A3        X      A,[B-]
024C 40 FC     IFBNE  00
024E 8C        POPA
024F A6        X      A,[B]
0250 8C        POPA
0251 9C FC     X      A,X
0253 8C        POPA
0254 9C FF     X      A,S
0256 8C        POPA
0257 9C F0     X      A,0F0
0259 8C        POPA
025A A0        RC 
025B 9F EF     LD     B,#0EF
025D 60 80     ANDSZ  A,#080
025F 7F        SBIT   07,[B]
0260 60 40     ANDSZ  A,#040
0262 7E        SBIT   06,[B]
0263 8C        POPA
0264 9C FE     X      A,B
0266 8C        POPA
0267 8F        RETI                 }

000C                                unsigned long main_loop_total;

                                    void main(void)
                                    {
077E                                        unsigned long count;

                                            DDR(PORTB,OOOOIIII); /* set upper nibble of PORTB as output */

                                            while(1)
                                            {
                                                                                                                                              /*_figure b_*/
0268 BC A5 F0  LD     0A5,#F0                 main_loop_total += count - 0x8000;
026B A1        SC 
026C DF 07     LD     S,#007
026E 9D 7E     LD     A,077E
0270 91 00     SUBC   A,#000
0272 DF 00     LD     S,#000
0274 5D        LD     B,#02
0275 A2        X      A,[B+]
0276 DF 07     LD     S,#007
0278 9D 7F     LD     A,077F
027A 91 80     SUBC   A,#080
027C DF 00     LD     S,#000
027E A6        X      A,[B]
027F A0        RC 
0280 CE        DRSZ   B
0281 AE        LD     A,[B]
0282 53        LD     B,#0C
0283 80        ADC    A,[B]
0284 A6        X      A,[B]
0285 9D 03     LD     A,0003
0287 52        LD     B,#0D
0288 80        ADC    A,[B]
                                                                                                                                              /*_figure b_*/
0289 A6        X      A,[B]                   count++;
028A 9F 7E     LD     B,#07E
028C A0        RC 
028D DF 07     LD     S,#007
028F AE        LD     A,[B]
0290 90 01     ADC    A,#001
0292 A2        X      A,[B+]
0293 AE        LD     A,[B]
0294 90 00     ADC    A,#000
0296 A6        X      A,[B]                 }
0297 22 6B     JMP    0026B
                                    }

    

If, in either the main loop or interrupt service routines, you don't use math library operations (multiply, divide, modulus) or 16-bit variables, you can reduce the amount of memory needed for preserving program state. To do so, define the symbol __NO16BIT_NOMATH_ISR in your program before cop8_isr.h is included. If you are using the BCLINK linker, this definition must be in the linker command file.

Figure 4-3. optimized SaveContext() and RestoreContext() rtccint3.lst

                                    void __INT(void)
                                    {
                                            SaveContext();
0102 9C 08     X      A,008
0104 9D FC     LD     A,X
0106 DC 09     LD     X,#009
0108 B2        X      A,[X+]
0109 9D FE     LD     A,B
010B B2        X      A,[X+]
010C 9D EF     LD     A,0EF
010E B2        X      A,[X+]
010F 9D F0     LD     A,0F0
0111 B2        X      A,[X+]

000E                                        unsigned int interrupt_temp;

0112 51        LD     B,#0E                 rtcc_total <<= interrupt_temp;
0113 AE        LD     A,[B]
0114 9C FC     X      A,X
0116 9D FC     LD     A,X
0118 92 00     IFEQ   A,#000
011A 09        JP     00124
011B 9D 0D     LD     A,00D
011D BD 0D 84  ADD    A,00D
0120 52        LD     B,#0D
0121 A6        X      A,[B]
0122 CC        DRSZ   X
0123 F7        JP     0011B
0124 51        LD     B,#0E                 interrupt_temp++;
0125 A6        X      A,[B]
0126 8A        INCA
0127 A6        X      A,[B]

                                            RestoreContext();
0128 53        LD     B,#0C
0129 AB        LD     A,[B-]
012A 9C F0     X      A,0F0
012C AE        LD     A,[B]
012D 84        ADD    A,[B]
012E BD EF 6F  RBIT   07,0EF
0131 88        IFC
0132 BD EF 7F  SBIT   07,0EF
0135 BD EF 6E  RBIT   06,0EF
0138 76        IFBIT  06,[B]
0139 A1        SC 
013A CE        DRSZ   B
013B AB        LD     A,[B-]
013C 9C FE     X      A,B
013E 9D 09     LD     A,009
0140 9C FC     X      A,X
0142 9D 08     LD     A,008
0144 8F        RETI                 }