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.

Reply via email to