ARM thumb: why call_via_rX?

Phil Blundell pb@nexus.co.uk
Fri Jan 25 06:04:00 GMT 2002


On Fri, 2002-01-25 at 12:17, Adrian von Bidder wrote:
> If it's sure that gcc does not generate any function returns with bx lr,
> but always does mov pc, lr or pop {..., pc} (which seems to be the
> case), function calls should be possible with just "mov lr, pc; mov pc,
> rX" in the non-interworking case.

Well, it's complicated.  In ARMv4T, "pop {pc}" isn't an
interworking-aware instruction; it will throw away bit zero and just
return in Thumb mode.  But in ARMv5, the semantics have changed to
complement the new "blx" instruction -- "pop {pc}" now looks at the low
bit and switches to ARM or Thumb mode in the same way that BX does. 
This is all a little bit unfortunate from the point of view of forwards
compatibility.

But yes, in principle you're right.  I don't think it would be all that
big a deal to allow you to write something like:

  void (*fp)(int) __attribute__ ((no-interworking)) = my_func;
  fp(1);

and get the code sequence you are looking for.

> Our CPU has an internal 8K static (fast) RAM, and external (slow) Flash.
> So my collegue had the idea of copying the most time-consuming code into
> the fast on chip RAM. So, of course, calls between non-copied and copied
> code with bl (such as calling call_via_rX) fail horribly.

Ah, I see.  If this copying is done just once at startup and then the
map stays fixed, you could write a custom linker script defining the
right memory regions, and then PC-relative branches would "just work"
(so long as the regions aren't too far apart, anyway).

p.



More information about the Gcc mailing list