arm/syscalls.c (get_errno): register constraints [PATCH]

Shaun Jackman
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, ...

	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;

	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.


2005-04-23  Shaun Jackman  <>

	* 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 @@
   return do_AngelSWI (AngelSWI_Reason_Errno, NULL);
-  asm ("swi %a0" : "r0" : "i" (SWI_GetErrno));
+  register r0 asm("r0");
+  asm ("swi %a1" : "=r"(r0) : "i" (SWI_GetErrno));
+  return r0;

More information about the Newlib mailing list