Search code examples
assemblyoptimizationavravr-gcc

Why is this code being generated by avr-gcc and how does it work?


This is a snippet of disassembled AVR code from a C project I'm working on. I noticed this curious code being generated, and I can't understand how it works. I'm assuming it's some sort of ridiculous optimization...

What is the explanation?

92:         ticks++;         // unsigned char ticks;
+0000009F:   91900104    LDS       R25,0x0104     Load direct from data space
+000000A1:   5F9F        SUBI      R25,0xFF       Subtract immediate
+000000A2:   93900104    STS       0x0104,R25     Store direct to data space
95:         if (ticks == 0) {
+000000A4:   2399        TST       R25            Test for Zero or Minus
+000000A5:   F009        BREQ      PC+0x02        Branch if equal
+000000A6:   C067        RJMP      PC+0x0068      Relative jump

Specifically, why does the second instruction subtract 0xFF from R25 instead of just INC R25?


Solution

  • The SUBI instruction can be used to add/subtract any 8 bit constant to/from an 8 bit value. It has the same cost as INC, i.e. instruction size and execution time. So SUBI is preferred by the compiler because it is more general. There is no corresponding ADDI instruction, probably because it would be redundant.