This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Branch instructions that depend on target distance


On Mon, 24 Feb 2020 11:14:44 +0000
Jozef Lawrynowicz <jozef.l@mittosystems.com> wrote:

> On Mon, 24 Feb 2020 12:05:28 +0100
> Petr Tesarik <ptesarik@suse.cz> wrote:
> 
> > Hi all,
> > 
> > I'm looking into reviving the efforts to port gcc to VideoCore IV [1].
> > One issue I've run into is the need to find out target branch distance
> > at compile time. I looked around, and it's not the first one
> > architecture with such requirement, but AFAICS it has never been solved
> > properly.
> > 
> > For example, AVR tracks instruction length. Later, ret_cond_branch()
> > selects between a branch instruction and an inverted branch followed by
> > an unconditional jump based on these calculated lengths.
> > 
> > This works great ... until there's some inline asm() statement, for
> > which gcc cannot keep track of the length attribute, so it is probably
> > taken as zero. Linker then fails with a cryptic message:
> >   
> > > relocation truncated to fit: R_AVR_7_PCREL against `no symbol'    
> 
> The MSP430 backend just always generates maximum range branch instructions,
> except for some special cases. We then rely on the linker to relax branch
> instructions to shorter range "jump" instructions when the destination is
> within range.
> 
> So the compiler output will always work, but not be the smallest possible code
> size.
> 
> For that relocation truncated to fit error message you want to check that the
> linker has the ability to relax whatever branch instruction it is failing on to
> a longer range branch.

But that would change the instruction length, so not really an option
AFAICS (unless I also switch to LTO).

Anyway, the situation is much worse on the VideoCore IV. The
alternatives here are:

1.
   addcmpbCC rx, 0, imm, target
   ; usually written as bCC rx, imm, target

2.
    cmp rx, imm
    bCC .+2
    j   target

The tricky part is that the addcmpbCC instruction does NOT modify
condition codes, while the cmp instruction does. Nothing you could
solve in the linker...

OK, it seems I'll have to go with the worst-case variant.

Petr T

> 
> Jozef
> > 
> > I can provide a minimal test case and report a bug if you want...
> > 
> > Developers work around the issue by rewriting their code when they
> > are bitten by this, but it is less than optimal, because you cannot
> > really get rid of all inline assembly, and it's in general
> > unpredictable where these inline asm() blocks will be placed by the
> > compiler.
> > 
> > OTOH, the avr backend is pretty outdated, so there may be a better
> > alternative that I'm just not seeing. Any hints?
> > 
> > Background: There is a port of the VC4 port of the LK embedded
> > kernel [2]. I have tried to build that kernel with optimization
> > turned on, but I'm getting:
> > 
> > compiling kernel/thread.c
> > /tmp/ccJFdnfX.s: Assembler messages:
> > /tmp/ccJFdnfX.s:1451: Error: operand out of range (64 not between
> > -64 and 63)
> > 
> > That's because there is an inline "di" (disable interrupts)
> > instruction inside a conditional statement in thread_yield(), which
> > causes this off-by-one miscalculation.
> > 
> > Petr T
> > 
> > [1] https://github.com/itszor/gcc-vc4
> > [2] https://github.com/librerpi/lk  
> 

Attachment: pgp1E1awPmruP.pgp
Description: Digitální podpis OpenPGP


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]