This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: Section layout with ld script for flash based ARM system :what's wrong?
- From: Nick Clifton <nickc at redhat dot com>
- To: Vincent Rubiolo <vincent dot rubiolo at st dot com>
- Cc: binutils at sources dot redhat dot com
- Date: Wed, 11 Jun 2003 17:38:20 +0100
- Subject: Re: Section layout with ld script for flash based ARM system :what's wrong?
- References: <3EE092C8.7080401@st.com><H0000cba183b4fb2.1055338118.eux100.sgp.st.com@MHS><3EE73C05.20901@st.com>
Hi Vincent,
> I followed Bill's advice to use gcc -mlong-calls flag, even if, as
> Richard pointed right, this has a performance cost (are there any
> other ways to do that only for those functions that need it? I am
> thinking about #pragma long_call, is this correct?)
Well this is gcc, so we prefer to use attributes, but yes:
extern void foo (void) __attribute__((long_call));
Will declare that foo should be called by the long call mechanism.
Other functions will be called normally. (Unless of course you use
-mlong-calls).
As it happens the #pragma long_calls and #pragma no_long_calls are
supported, but I do not recommend using this mechanism.
> I nevertheless still have problems with _call_via_rX stubs.
Ah yes. This is a known "issue". These stubs are held in the
libgcc.a library, which is presumably being linked with the rest of
your "normal" code and relocated to sit down in low RAM. The code in
Flash RAM however tries to use them to perform the long calls down
into low RAM and this causes the problems.
There is a workaround if you are using ARMv5 architecture chips - the
BLX instruction. This instruction can be used for long calls and it
does not need the _call_via_rX stubs. There is a patch for gcc which
implements this, although it has not been accepted into the official
sources. You can try it out if you like:
Cheers
Nick
Index: gcc/config/arm/arm.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.md,v
retrieving revision 1.135
diff -c -3 -p -r1.135 arm.md
*** gcc/config/arm/arm.md 2 Jun 2003 03:53:54 -0000 1.135
--- gcc/config/arm/arm.md 11 Jun 2003 16:38:03 -0000
***************
*** 5965,5974 ****
{
if (TARGET_CALLER_INTERWORKING)
return \"bl\\t%__interwork_call_via_%0\";
else
return \"bl\\t%__call_via_%0\";
}"
! [(set_attr "type" "call")]
)
(define_insn "*call_value_indirect"
--- 5965,5980 ----
{
if (TARGET_CALLER_INTERWORKING)
return \"bl\\t%__interwork_call_via_%0\";
+ else if (arm_arch5)
+ return \"blx\\t%0\";
+ else if (TARGET_LONG_CALLS)
+ /* For long calls the __call_via functions might not be near
+ this branch, so we have to synthesise their actions. */
+ return \"bl\\t0f\\n\\tb\\t1f\\n0:\\tbx\\t%0\\n1:\";
else
return \"bl\\t%__call_via_%0\";
}"
! [(set_attr "type" "call")(set_attr "length" "8")]
)
(define_insn "*call_value_indirect"
***************
*** 5982,5991 ****
{
if (TARGET_CALLER_INTERWORKING)
return \"bl\\t%__interwork_call_via_%1\";
else
return \"bl\\t%__call_via_%1\";
}"
! [(set_attr "type" "call")]
)
(define_expand "call_value"
--- 5986,6003 ----
{
if (TARGET_CALLER_INTERWORKING)
return \"bl\\t%__interwork_call_via_%1\";
+ else if (arm_arch5)
+ return \"blx\\t%1\";
+ else if (TARGET_LONG_CALLS)
+ /* For long calls the __call_via functions might not be near
+ this branch, so we have to synthesise their actions. */
+ return \"bl\\t0f\\n\\tb\\t1f\\n0:\\tbx\\t%1\\n1:\";
else
return \"bl\\t%__call_via_%1\";
}"
! [(set_attr "type" "call")(set_attr "length" "8")]
)
(define_expand "call_value"