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
?
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.
tl;dr the compiler was designed to use the more portable, efficient & general solution here.
The SUBI
instruction sets C
(carry) and H
(half-carry) CPU flags for use with subsequent instructions (there is no ADDI
in 8-bit AVR BTW, so to add an immediate value of x
we subtract -x
from it), whereas INC
does not. Since both SUBI
& INC
have 2 bytes of length and execute during 1 clock cycle, you lose nothing by using SUBI
- OTOH, if you use a 8-bit-sized counter, you can then easily detect if it has rolled over (by BRCC
/BRCS
), and if you'd have a 16- or 32-bit-sized counter, it allows you to increment it in a very simple way - with just INC
, 0x00FF
would get increased to 0x0000
, so you'd have to check if the lowest byte is 0xFF
before INC
ing. OTOH, with SUBI
you just SUBI -1
the lowest byte, and then ADC 0
for the following bytes, assuring all the potential carry bits has been 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With