Inline ARM assembler and the sp register

Richard Tew
Tue May 2 10:04:00 GMT 2006


I am using the inline assembly functionality of gcc (gcc 4.1.0
compiled as part of the devkitpro/devkitarm package which
uses mingw/msys on Windows).  What I am trying to do is
port Stackless Python, which copies portions of the stack
off and back on, as it switches between microthreads.

The problem is, gcc preserves the stack pointer on entry to the
function and restores it at the end, so while I may copy around
portions of the stack with the presumption my modified stack
pointer will be used on exit of the function, what I actually get
is the modified stack, but the old stack pointer restored over
my modified one.

I can hack a solution.  Looking at the disassembly in the
debugger I am using, I see that sp is preserved in r7, so if I
modify my inline assembler to modify r7 instead of sp,
Stackless Python works fine.

What I want to be able to do, is work out why gcc is preserving
sp and to prevent it from doing so.  I looked at another function
and sp didn't seem to be preserved in that, so I assume that
gcc detects that I clobber it (even if I do not specify that I do
in my inline assembler) and preserves it because of this.

Can anyone help me?  I have read the inline assembly
documentation, and as far as I can tell, this should work
as long as I don't specify sp in the clobbered register list.
And the other platforms which Stackless Python supports
do not do anything different, than what I am doing, other
than using the corresponding assembler instructions for
their given platform.

Here is the function:

/* gcc will not compile this if v4 is included. */
#define REGS_TO_SAVE "a1", "a2", "a3", "a4", "v1", "v2", "v3",
/*"v4",*/ "v5", "v6", "sl", "fp", "ip", "lr"

static int
 register int *stackref, stsizediff;
 __asm__ volatile ("" : : : REGS_TO_SAVE);
 __asm__ ("mov %0, sp" : "=g" (stackref) : );
  SLP_SAVE_STATE(sp, stsizediff);
  __asm__ volatile (
      "mov r0, %0\n"
      "add sp, sp, r0\n"
      : "g" (stsizediff)
      : "r0"
  return 0;
 __asm__ volatile ("" : : : REGS_TO_SAVE);

I have even tried commenting out the REGS_TO_SAVE lines,
for the sake of it, but to no effect.

Anyway, if anyone has any ideas on how I can get
around this problem besides adding the hack of
modifying the preserved register

"add r7, r7, r0\n"

Please let me know.


More information about the Gcc-help mailing list