arm/syscalls.c (get_errno): register constraints [PATCH]
Jeff Johnston
jjohnstn@redhat.com
Thu Apr 28 18:42:00 GMT 2005
Patch checked in, thanks.
-- Jeff J.
Shaun Jackman wrote:
> 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