This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils 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: Section layout with ld script for flash based ARM system :what's wrong?


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"


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