arm/syscalls.c (get_errno): register constraints [PATCH]
Shaun Jackman
sjackman@gmail.com
Sat Apr 23 20:09:00 GMT 2005
The following snippet from libgloss/sys/arm/syscalls.c (and
libc/sys/arm/syscalls.c), slightly modified for clarity here, does not
specify an output register in the asm statement producing bad code
when inlined and optimised by gcc.
static int get_errno (void)
{
asm ("swi %a0" :: "i" (SWI_GetErrno));
}
static int error (int result)
{
*__errno() = get_errno ();
return result;
}
gcc generates the following assembler, ...
error:
push {r4, r5, lr}
mov r4, r0
bl __errno
swi 96
str r5, [r0, #0]
mov r0, r4
pop {r4, r5, pc}
... which clobbers the return value from the __errno call.
This code has the intended effect:
static int get_errno (void)
{
register r0 asm("r0");
asm ("swi %a1" : "=r"(r0) : "i" (SWI_GetErrno));
return r0;
}
error:
push {r4, lr}
mov r4, r0
bl __errno
mov r3, r0
swi 96
str r0, [r3, #0]
mov r0, r4
pop {r4, pc}
The functions _swiread, _swiwrite, _swiclose, _exit (if it were ever
to return), and _kill suffer from the same problem. These functions
are currently static though, so gcc does not inline them and the
problem does not present itself. If these functions were made static
though -- I don't see why they shouldn't be -- the problem could pop
up again.
Cheers,
Shaun
2005-04-23 Shaun Jackman <sjackman@gmail.com>
* libgloss/syscalls.c (get_errno): Add an output register constraint.
--- libgloss/arm/syscalls.c- 2005-04-22 21:26:49.000000000 -0700
+++ libgloss/arm/syscalls.c 2005-04-23 10:20:49.000000000 -0700
@@ -187,7 +187,9 @@
#ifdef ARM_RDI_MONITOR
return do_AngelSWI (AngelSWI_Reason_Errno, NULL);
#else
- asm ("swi %a0" : "r0" : "i" (SWI_GetErrno));
+ register r0 asm("r0");
+ asm ("swi %a1" : "=r"(r0) : "i" (SWI_GetErrno));
+ return r0;
#endif
}
More information about the Newlib
mailing list