summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobie Basak <robie.basak@canonical.com>2014-10-14 13:16:22 +0100
committerRobie Basak <robie.basak@canonical.com>2014-10-14 17:44:34 +0100
commit505c91a68aaf5ab56325affd4d8581b32b649cf4 (patch)
tree577cfeda06cb3cb9c8948955d8b6f72b9dff1141
parente31e76af477853d5e35418f60e2562ca94fdee0e (diff)
downloadgreenlet-505c91a68aaf5ab56325affd4d8581b32b649cf4.tar.gz
arm32: force return value from asm
In my case, instead of a simple "mov r0, #0", the optimizer had done this: Between calls to slp_save_state and slp_restore_state, it saved the value now guaranteed to be 0 using "str r0, [r7]". Now, at the end, it restores that value into r0 using "ldr r3, [r7]" and then "mov r0, r3". It isn't clear to me that intermediate values managed by the compiler, like this one at [r7], would be preserved in the stack this way, especially as at this point we're in a "different" stack (unknown to the optimizer). Instead, prevent the optimizer from re-using a previous result like this by forcing it to rely on the inline assembly to produce the result. This fixes test failures on Ubuntu Utopic using gcc 4.9.1 (-5ubuntu1). I think even this is still a hack though, and not guaranteed to work. Ultimately, gcc can even re-order the "__asm__ volatile" functions at will around the entire function, or just wrap each REGS_TO_SAVE clobbering call with a simple push/pop, thus not preserving the registers between stack switches. The only way I can see of doing this without relying on undefined compiler behaviour is to write the entire slp_switch function in assembly for each architecture, instead of inlining it into a C function for code reuse.
-rw-r--r--platform/switch_arm32_gcc.h5
1 files changed, 3 insertions, 2 deletions
diff --git a/platform/switch_arm32_gcc.h b/platform/switch_arm32_gcc.h
index c6e160d..e1cd797 100644
--- a/platform/switch_arm32_gcc.h
+++ b/platform/switch_arm32_gcc.h
@@ -54,6 +54,7 @@ slp_switch(void)
{
void *fp;
register int *stackref, stsizediff;
+ int result;
__asm__ volatile ("" : : : REGS_TO_SAVE);
__asm__ volatile ("mov r0," REG_FP "\n\tstr r0,%0" : "=m" (fp) : : "r0");
__asm__ ("mov %0," REG_SP : "=r" (stackref));
@@ -67,9 +68,9 @@ slp_switch(void)
);
SLP_RESTORE_STATE();
}
- __asm__ volatile ("ldr r0,%0\n\tmov " REG_FP ",r0" : : "m" (fp) : "r0");
+ __asm__ volatile ("ldr r0,%1\n\tmov " REG_FP ",r0\n\tmov %0, #0" : "=r" (result) : "m" (fp) : "r0");
__asm__ volatile ("" : : : REGS_TO_SAVE);
- return 0;
+ return result;
}
#endif \ No newline at end of file