https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82150
Bug ID: 82150 Summary: Produces a branch prefetch which causes a hang Product: gcc Version: 7.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: david.welch at netronome dot com Target Milestone: --- export TARGET=arm-none-eabi ../gcc-$GCCVER/configure --target=$TARGET --prefix=$PREFIX --without-headers --with-newlib --with-gnu-as --with-gnu-ld --enable-languages='c' but we first found this on a 4.8.3, dont have a reason to assume it applies to all versions. take something like this unsigned int more_fun ( unsigned int ); unsigned int fun ( void ) { return(more_fun(0x12344700)+1); } arm-none-eabi-gcc -mthumb -march=armv6 -O2 -c so.c -o so.o 00000000 <fun>: 0: b510 push {r4, lr} 2: 4802 ldr r0, [pc, #8] ; (c <fun+0xc>) 4: f7ff fffe bl 0 <more_fun> 8: 3001 adds r0, #1 a: bd10 pop {r4, pc} c: 12344700 eorsne r4, r4, #0, 14 And there is the problem. This is not limited to thumb mode unsigned int more_fun ( unsigned int ); unsigned int fun ( void ) { return(more_fun(0xe12fff10)+1); } 00000000 <fun>: 0: e92d4010 push {r4, lr} 4: e59f0008 ldr r0, [pc, #8] ; 14 <fun+0x14> 8: ebfffffe bl 0 <more_fun> c: e2800001 add r0, r0, #1 10: e8bd8010 pop {r4, pc} 14: e12fff10 bx r0 same problem. Found on an arm11 mpcore but assume that the older arm11s and possibly even armv7s have this issue, will see when I get there. The core does not see pop pc as an unconditional branch it continues to process the instructions in the pipe while the pop is finishing, it prefetches the address in r0 in both of the above cases, because the DATA that follows the pop happens to resemble an instruction, specifically bx but I wonder if other instructions are a problem as well. The prefetch reads the fetch line at whatever address that register that happens to be encoded. This can cause a read of perpherals which are clear on read, or pull a byte out of a uart, or in our case touch an address that doesnt answer on the axi bus and hang the processor. Now because the armv4t didnt support mode switching with a pop using -march=armv4t produces code that doesnt cause the processor to fail. 00000000 <fun>: 0: b510 push {r4, lr} 2: 4803 ldr r0, [pc, #12] ; (10 <fun+0x10>) 4: f7ff fffe bl 0 <more_fun> 8: 3001 adds r0, #1 a: bc10 pop {r4} c: bc02 pop {r1} e: 4708 bx r1 10: 12344700 eorsne r4, r4, #0, 14 I cant possibly be the first person to see this after all of these years (and although I cant think off hand of another instruction set where the pc is also treated like a GPR, there are other targets that are affected), so I am hoping there is already a command line switch other than downgrading wholesale to armvt. If not can we add a command line switch to avoid this problem? I would think a branch to self instruction following the pop would work or like armv4t dont pop into the pc but in arm pop to lr and then bx lr or thumb as you do in armv4t pop to r0-r3 and bx to that.