This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug target/82150] New: Produces a branch prefetch which causes a hang
- From: "david.welch at netronome dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Fri, 08 Sep 2017 17:14:33 +0000
- Subject: [Bug target/82150] New: Produces a branch prefetch which causes a hang
- Auto-submitted: auto-generated
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.