Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2015-12

Capability CPUARM_HAS_BLX_LABEL with ARM instruction set

9 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Garry Wood

Hello,

I have been working on some embedded (no OS) development on ARMv6 and ARMv7 (Raspberry Pi and Raspberry Pi 2) using FPC 3.1.1 trunk.

Because these devices have a fairly large amount of memory I have been using ARM instruction set (-CIARM option) to simplify the assembler code required for the low level interfaces, however early on I noticed that if I specify the options -CpARMV7A (or -CpARMV6) and -CIARM I end up with code that doesn't work.

I traced the problem to the use of BLX <Label> instructions which according to the ARM documentation seem to always causes an unconditional change to Thumb state. If I remove the CPUARM_HAS_BLX_LABEL capability and rebuild the compiler the code produced uses only BL <Label> and always works correctly. There seems to be no problem with BLX <Register> or BX <Register> instructions which use bit[0] of the register to determine the target state.

There appear to be only two places in the compiler and RTL code where CPUARM_HAS_BLX_LABEL and ARM state needs to be handled, these are:

\source\compiler\arm\cgcpu.pas

Which in tbasecgarm.a_call_name has something like

                        if (CPUARM_HAS_BLX_LABEL in cpu_capabilities[current_settings.cputype]) and
                          { WinCE GNU AS (not sure if this applies in general) does not support BLX imm }
                          (target_info.systemsystem_arm_wince) then
                          branchopcode:=A_BLX
                        else
                          branchopcode:=A_BL;

This could easily be changed to

                        if (CPUARM_HAS_BLX_LABEL in cpu_capabilities[current_settings.cputype]) and
                          { WinCE GNU AS (not sure if this applies in general) does not support BLX imm }
                          (target_info.systemsystem_arm_wince) and
                          (current_settings.instructionset  is_arm) then
                          branchopcode:=A_BLX
                        else
                          branchopcode:=A_BL;

to account for the ARM state.

The other occurrence is in the assembler code in \source\rtl\arm\arm.inc for fpc_ansistr_decr_ref which has

{$if defined(CPUARM_HAS_BX) and not(defined(WINCE))}
  blx     InterLockedDecrement

This should probably be changed to defined(CPUARM_HAS_BLX_LABEL) instead but that doesn't deal with the selected instruction set (ARM or Thumb). Obviously the CPU capabilities are available as defines at this point but I cannot actually find anywhere that the IS_ARM / IS_THUMB settings also end up as defines.

Before I go ahead and log this as a bug report is there anyone who can comment on whether :

a) There is something I am misunderstanding in the ARM documentation about BLX <Label> and the switch to Thumb state?

b) How the use of BLX <Label> in \rtl\arm\arm.inc might be resolved (is there actually a define that reflects ARM or Thumb state selection)?

One more thing, just wanted to give a big congratulations to the FPC dev team. I have been working on this project for several months and have a fully working embedded core including pre-emptive threading, lock primitives, multicore support, memory management, hardware exceptions, interrupt handling, DMA, USB, filesystem, network etc which is 100% Free Pascal and this is the only issue I have encountered that I could directly trace to FPC itself. Thanks to you all for such a powerful compiler!

Thanks,

Garry Wood.

Reply by email

Anthony Walter
to Garry Wood

Hello Gary and thanks go out to both the FPC and Lazarus teams as well. I don't want to hijack your thread, but I too am using FPC on the Pi, albeit not to the level you've gone.

I believe the FPC community has the opportunity to expand to a new younger audience with the Pi. With this in mind I believe it's important we call to action as many knowledgeable people involved with FPC and Lazarus. We can work together on materials or enhancements when presenting FPC and Lazarus to Pi users. For example creating worksheet oriented tutorials showing the easy and strength of FPC in an exciting way.

To that end I've created two friendly reduced footprint FPC 3.0 and Lazarus Pi setup scripts. One script installs a minimal FPC 3.0 compiler (it doesn't interfere with existing FPC per usual me), and the other is a reduced FPC and Lazarus (again no interference).

Minimal FPC 3.0 for P bundled as tar.gz:
http://cache.getlazarus.org/archives/fpc-3.0.0.raspberry-min.tar.gz Reduced FPC 3.0 + Lazarus bundled as a pure script: http://www.getlazarus.org/download/?platform=raspberry

I've also been working on two graphics + inputs systems which operate outside of the windowing system. One built around creating full screen graphics with GLESv2, the other built around full screen graphics with OpenVG. In my development so far I'm impressed both with the speed and complexity of graphics the Pi2 GPU hardware + drivers can deliver, and with how nice the FPC language can be in creating an object oriented class library to simplify everything. I plan to create a Raspberry Pi worksheet section for both at http://www.getlazarus.org.

In the end I think when presented correctly, FPC should be the obvious choice to Pi users over C/C++, Python, Java, or Go, and that we (our community) should be working together to achieve the best possible Pi user experience with regards to FPC and Lazarus.

Reply by email

Jonas Maebe
to Anthony Walter
Anthony Walter wrote 13 lines
Because these devices have a fairly large amount of memory I have been using ARM instruction set (-CIARM option) to simplify the assembler code required for the low level interfaces, however early on I noticed that if I specify the options -CpARMV7A (or -CpARMV6) and –CIARM I end up with code that doesn’t work. I traced the problem to the use of BLX <Label> instructions which according to the ARM documentation seem to always causes an unconditional change to Thumb state. If I remove the CPUARM_HAS_BLX_LABEL capability and rebuild the compiler the code produced uses only BL <Label> and always works correctly. There seems to be no problem with BLX <Register> or BX <Register> instructions which use bit[0] of the register to determine the target state.

The compiler and assembler mark which code is ARM and which is Thumb. Normally, when the linker processes the object files, it will replace the blx instructions with bl if they go from ARM to ARM or from Thumb to Thumb. The reason that a compiler/assembler cannot do this, is that the target of a call may be in another object file and the compiler/assembler cannot know whether this object file has been compiled in ARM or Thumb mode.

Are you not processing the generated code with a linker at all?

Jonas

Reply by email

Anthony Walter
to Sven Barth

Sven, the FPC community is not that large as that of C, or Java, or Go. Our figurative slice of potential users is reduced further when qualified as FPC on the Raspberry Pi. My response to Garry was a sort of "Hey we both like FPC and Pi, maybe some of us can band together to benefit FPC on Pi". My thinking was that splitting the conversation into separate thread would create more fracture and less union.

It is up to Gary to decide if my comment was an unwanted diversion. Gary, if you are reading this and feel I was diverting your original message in an unwanted manner, then I apologize.

Reply by email

Sven Barth
to Anthony Walter
Anthony Walter wrote 6 lines
Sven, the FPC community is not that large as that of C, or Java, or Go. Our figurative slice of potential users is reduced further when qualified as FPC on the Raspberry Pi. My response to Garry was a sort of "Hey we both like FPC and Pi, maybe some of us can band together to benefit FPC on Pi". My thinking was that splitting the conversation into separate thread would create more fracture and less union.

This has nothing to do with the size of the community. Everyone who's subscribed to the list gets all mails anyway and you hijacking another thread will probably even lead to *less* people reading your message (because they are not interested in the CPUARM_HAS_BLX_LABEL topic for example (I for example simply mark complete threads I'm not interested in as "read" when I see they have new messages)). In addition this is more a topic for fpc-pascal than fpc-devel.

It is up to Gary to decide if my comment was an unwanted diversion. Gary, if you are reading this and feel I was diverting your original message in an unwanted manner, then I apologize.

Honestly, no, that's not up to Gary to decide. This is part of the mailing list etiquette that is followed here on this list and which is rather standard on mailing lists anyway. At least change the subject and add "Was: OLD TITLE" or something like this or better yet: do not hijack other threads.

Regards,
Sven

Reply by email

Jeppe Johansen
to Jonas Maebe: The compiler and assembler mark which code is ARM and which is Thumb. Normally, when the…
Jonas Maebe wrote 27 lines
Anthony Walter wrote: > Because these devices have a fairly large amount of memory I have been > using ARM instruction set (-CIARM option) to simplify the assembler code > required for the low level interfaces, however early on I noticed that > if I specify the options -CpARMV7A (or -CpARMV6) and –CIARM I end up > with code that doesn’t work. > > I traced the problem to the use of BLX <Label> instructions which > according to the ARM documentation seem to always causes an > unconditional change to Thumb state. If I remove the > CPUARM_HAS_BLX_LABEL capability and rebuild the compiler the code > produced uses only BL <Label> and always works correctly. There seems to > be no problem with BLX <Register> or BX <Register> instructions which > use bit[0] of the register to determine the target state. The compiler and assembler mark which code is ARM and which is Thumb. Normally, when the linker processes the object files, it will replace the blx instructions with bl if they go from ARM to ARM or from Thumb to Thumb. The reason that a compiler/assembler cannot do this, is that the target of a call may be in another object file and the compiler/assembler cannot know whether this object file has been compiled in ARM or Thumb mode. Are you not processing the generated code with a linker at all? Jonas

Just adding to Jonas's answer here.

While it's true that BLX always changes instructions set, I've heard some reports indicating that some assembler/linker combinations on OSX (apparently clang based?) have been behaving strangely with this lately. GCC+binutils have always been following the "emit blx and let the linker fix it" recipe, just as fpc does.

Best Regards,
Jeppe

Reply by email

Garry Wood
to Jeppe Johansen
Jonas Maebe wrote 20 lines
> The compiler and assembler mark which code is ARM and which is Thumb. > Normally, when the linker processes the object files, it will replace > the blx instructions with bl if they go from ARM to ARM or from Thumb > to Thumb. The reason that a compiler/assembler cannot do this, is that > the target of a call may be in another object file and the > compiler/assembler cannot know whether this object file has been > compiled in ARM or Thumb mode. > > Are you not processing the generated code with a linker at all? > > > Jonas Just adding to Jonas's answer here. While it's true that BLX always changes instructions set, I've heard some reports indicating that some assembler/linker combinations on OSX (apparently clang based?) have been behaving >strangely with this lately. GCC+binutils have always been following the "emit blx and let the linker fix it" recipe, just as fpc does. Best Regards, Jeppe

I'm certainly using both as and ld (both arm-none-eabi for Win32 from launchpad.net) to produce the binary. The linker outputs an elf and I modified the MakeExecutable method in the compiler to do an objcopy after the linker to obtain a binary image. I also get it to do objdump on the elf to produce a list file which is where I see the blx <label> appearing.

I'll do some more searching based on the additional information from Jeppe to see if there is maybe a reported issue or an additional linker switch or something that is required.

Thanks for the info.

Garry.

Reply by email

Garry Wood
to Garry Wood
Show quoted text 14 lines
>While it's true that BLX always changes instructions set, I've heard some reports indicating that some assembler/linker combinations on OSX (apparently clang based?) have been behaving >>strangely with this lately. >GCC+binutils have always been following the "emit blx and let the linker >fix it" recipe, just as fpc does. > >Best Regards, >Jeppe I'm certainly using both as and ld (both arm-none-eabi for Win32 from launchpad.net) to produce the binary. The linker outputs an elf and I modified the MakeExecutable method in the compiler >to do an objcopy after the linker to obtain a binary image. I also get it to do objdump on the elf to produce a list file which is where I see the blx <label> appearing. I'll do some more searching based on the additional information from Jeppe to see if there is maybe a reported issue or an additional linker switch or something that is required. Thanks for the info. Garry.

Just following up on this, I noticed today a commit from Florian on December 29 that removes the use of BLX <Label> from both cgcpu.pas and arm.inc

Obviously someone here was able to obtain more info, which is lucky because my searching wasn't coming up with to whoever worked out that both gcc and clang now use bl instead of blx, this completely resolves the issue for me with fpc as well.

Garry.

Reply by email