This is a follow up question to this.
I'm writing code for an __AVR_HAVE_LPMX__
processor (avr25) using
when I use lpm rd, Z
in inline assembly, the compiler always translates this to lpm rd,Z+
(excerpt from lss-file):
asm volatile("lpm r24,Z");
248: 84 91 lpm r24, Z+
which is bad, if it's used in successive access to a look-up-table. The look-up value might be 0xff
, so this unnecessarily increments ZH
(r31
) thus corrupting this solution.
Any suggestions to circumvent this behavior?
There is nothing wrong in the solution; your disassembler (avr-objdump -d
, part of binutils
package) is buggy.
See page 97 of the Atmel AVR instruction set manual (PDF). The lpm
instruction variants are encoded as
1001 0101 1100 1000 = 0x95C8 lpm r0,Z
1001 000? ???? 0100 = 0x9??4 lpm r?,Z
1001 000? ???? 0101 = 0x9??5 lpm r?,Z+
Assuming we trust the Atmel documentation better than your disassembler, then
84 91 lpm r24,Z
whereas
85 91 lpm r24,Z+
Indeed, avr-gcc (GCC) 4.8.2 compiles the inline assembly to the same two bytes (84 91
) using avr-gcc-4.8.2 -O2 -fomit-frame-pointer -mmcu=avr25
, and lists it as lpm r24,Z
in the assembly source file (using -S
option); when compiled to an object file, and disassembling with avr-objdump (GNU binutils) 2.23.1 using avr-objdump -d
, the instruction is still 84 91
lpm r24,Z
.
This makes me believe it is a bug in avr-objdump (part of GNU binutils). Ah yes, reported here, and apparently fixed in binutils-2.23.1 in October 2013.
In short, only the disassembly is affected; the disassembly incorrectly shows Z+
when it should show Z
. It does not affect the generated code, only the human-readable output is incorrect. To fix, upgrade to binutils version 2.23.1 or later. If you can't, don't worry: you can safely ignore this error, as it only affects the human-readable disassembly.
Questions?