------- Comment #2 from Eric dot Doenges at betty-tv dot com 2006-04-04 09:13 ------- (In reply to comment #1) > This code is undefined: > len = ((unsigned int)&_ram_erase_sector_end > - (unsigned int)&_ram_erase_sector_start) / sizeof(unsigned int); > > That is obviously undefined as taking the difference between two pointers > which > are not in the same array is undefined code. > > Even the comparision: > p_rom < p_end; > is undefined. > In the code I took this snippet from, _ram_erase_sector_start and _ram_erase_sector_end are symbols generated by the linker at the start and the end of a special segment which I need to copy to ram, so I would argue that these pointers do in fact refer to the same "array" (in this case, the "array" is the entire flash memory).
However, none of this should affect the decision to use (or not to use) the post-indexed addressing mode. If I replace the for loop with a for (len = 100; len > 0; --len), the quality of the generated code actually degrades even further: ldr r2, .L7 ldr r1, .L7+4 @ lr needed for prologue .L2: ldr r3, [r1, #-4] str r3, [r2, #-4] ldr r3, .L7+8 add r2, r2, #4 cmp r2, r3 add r1, r1, #4 bne .L2 bx lr While I thinks it's nifty that gcc recognizes that it doesn't need to keep the len variable, but instead uses p_ram to determine when the loop is finished, I also think it's pretty brain-dead that it won't use post-indexed addressing for either the ldr or str in the loop. And why it thinks it needs to load the constant end address to compare against every time inside the loop instead of once into a scratch register outside the loop is anyone's guess. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27016