https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50749
--- Comment #22 from Urja Rannikko <urjaman at gmail dot com> ---
All of the 3 pointer regs (X,Y,Z) can do post-inc operations, but only Y and Z
can do displacement (which is what gcc tries to use, even when the increment
operation would be better all around since we usually want the +4 pointer).
The given code wasnt meant to be anywhere near the real code, just a code that
shows the behaviour exists. The real code is just a function with lots going on
involving loading 32-bit values from pointers.
This code is WIP and i was just looking how it'll end up compiled, but for your
curiosity, here's a fragment (not enough to compile), with a comment added on
the part where i found the ld, adiw, ld, sbiw, adiw, ld, sbiw, adiw, ..
sequence, but AFAIK it could be triggered at any usage of inlined buf2u32:
static uint32_t buf2u32(uint8_t *buf) {
return *(uint32_t*)buf;
}
static uint8_t do_exec_opbuf_extwrite(uint8_t *ewsq, uint32_t addr, uint8_t
*buf, uint16_t dlen) {
uint8_t* end = ewsq + ewsq[0] + 1;
for (uint16_t i=0;i<dlen;i++,addr++) {
uint8_t c = *buf++;
uint8_t *cmd;
for (cmd=ewsq+1;cmd<end;) {
uint8_t op = *cmd++;
uint8_t rop = op&0x3F;
if (rop==S_CMD_O_WRITEB) {
uint32_t ra;
uint8_t rc;
if (op & 0x80) {
ra = addr;
} else {
ra = buf2u32(cmd);
cmd += 4;
}
if (op & 0x40) {
rc = c;
} else {
rc = *cmd++;
}
flash_write(ra,rc);
continue;
}
if (rop==S_CMD_O_DELAY) {
udelay(buf2u32(cmd));
cmd += 4;
continue;
}
if ((rop==S_CMD_O_POLL)||(rop==S_CMD_O_POLL_DLY)) {
uint8_t details = *cmd++;
uint8_t mask = pgm_read_byte(
&(bit_mask_lut[details&7]) );
uint32_t ra = addr;
uint32_t usecs = 0;
if ((op & 0x40)&&(!(details & 0x10))) {
if (c & mask) {
details |= 0x20;
} else {
details &= ~0x20;
}
}
if (!(op & 0x80)) {
ra = buf2u32(cmd); // Problem Here
cmd += 4;
}
if (rop == S_CMD_O_POLL_DLY) {
usecs = buf2u32(cmd);
cmd += 4;
}
do_exec_poll(details,mask,ra,usecs);
continue;
}
return 1;
}
if (cmd>end) return 1;
}
return 0;
}
If i end up liking this code enough it'll end up in a branch at
https://github.com/urjaman/libfrser