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

This is a fragment of the disassembled AVR code from project C that I am working on. I noticed that this curious code is being generated, and I cannot understand how it works. I guess this is some kind 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 

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

+4
source share
2 answers

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, that is, the size of the instruction and the execution time. Therefore, SUBI prefers the compiler because it is more general. There is no corresponding ADDI instruction, probably because it will be redundant.

+4
source

tl; The dr compiler was designed to use a more portable, efficient and generic solution here.

The SUBI set contains the CPU tags C (carry) and H (half-carry) for use with subsequent ones (in the 8-bit AVR BTW there is no ADDI , therefore, to add the immediate value of x we subtract -x from it), while INC does not. Since both SUBI and INC are 2 bytes long and run for 1 clock, you lose nothing using SUBI - OTOH, if you use an 8-bit counter, you can easily find ( BRCC / BRCS ), and if you have there will be a 16 or 32 bit counter, this will allow you to increase it in a very simple way - only with INC , 0x00FF will be increased to 0x0000 , so you will need to check if the low byte 0xFF before INC ing. OTOH, with SUBI you are just SUBI -1 low byte, and then ADC 0 for the next bytes, ensuring that all potential carry bits are accounted for.

Further reading:

https://lists.gnu.org/archive/html/avr-gcc-list/2008-11/msg00029.html

http://avr-gcc-list.nongnu.narkive.com/SMMzdBkW/foo-subi-vs-inc

+3
source

All Articles