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

Reply via email to