This is the mail archive of the libc-ports@sources.redhat.com mailing list for the libc-ports project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

ARM setjmp/longjmp support for iWMMXt


This patch teaches glibc's ARM EABI setjmp and longjmp to save and restore 
iWMMXt registers, if they are present and the kernel announces this with 
HWCAP_IWMMXT, as done for VFP registers.  The HWCAP_IWMMXT setting has 
been accepted for the kernel, see 
<http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=3756/1>.

At present, these functions get HWCAP_VFP from <asm/procinfo.h>.  Getting 
HWCAP_IWMMXT that way would be a problem because it would require very new 
git kernel headers; making the code conditional on the define might also 
be undesirable, since the kernel headers don't necessarily correspond 
exactly to the kernel being used at runtime.

Use of <asm/procinfo.h>, a Linux-specific kernel header, in 
sysdeps/arm/eabi, is also an abstraction violation.  glibc already 
hardcodes a list of HWCAP values in dl-procinfo.h and dl-procinfo.c.  I 
decided it would be better to move the hardcoded list to use #defines and 
be in sysdep.h, so that they can be used from assembly.  (PowerPC also 
uses #defines in sysdep.h for HWCAP values.)  So this patch follows that 
approach.  (In principle I think all the other files in sysdeps/arm/eabi 
should also use sysdep.h not asm/procinfo.h for HWCAP_VFP.)

2006-08-18  Joseph Myers  <joseph@codesourcery.com>

	* sysdeps/unix/sysv/linux/arm/dl-procinfo.c (_dl_arm_cap_flags):
	Add "java" and "iwmmxt".
	* sysdeps/unix/sysv/linux/arm/dl-procinfo.h: Use <sysdep.h> for
	HWCAP values.
	(_DL_HWCAP_COUNT): Increase to 10.
	* sysdeps/unix/sysv/linux/arm/sysdep.h (HWCAP_ARM_SWP,
	HWCAP_ARM_HALF, HWCAP_ARM_THUMB, HWCAP_ARM_26BIT,
	HWCAP_ARM_FAST_MULT, HWCAP_ARM_FPA, HWCAP_ARM_VFP, HWCAP_ARM_EDSP,
	HWCAP_ARM_JAVA, HWCAP_ARM_IWMMXT): Define.
	* sysdeps/arm/eabi/setjmp.S (__sigsetjmp): Save iWMMXt registers
	if HWCAP_ARM_IWMMXT set.  Don't include <asm/procinfo.h>.  Use
	HWCAP_ARM_VFP instead of HWCAP_VFP.
	* sysdeps/arm/eabi/__longjmp.S (__longjmp): Restore iWMMXt
	registers if HWCAP_ARM_IWMMXT set.  Don't include
	<asm/procinfo.h>.  Use HWCAP_ARM_VFP instead of HWCAP_VFP.

Index: sysdeps/arm/eabi/__longjmp.S
===================================================================
RCS file: /cvs/glibc/ports/sysdeps/arm/eabi/__longjmp.S,v
retrieving revision 1.1
diff -u -r1.1 __longjmp.S
--- sysdeps/arm/eabi/__longjmp.S	10 Oct 2005 15:29:32 -0000	1.1
+++ sysdeps/arm/eabi/__longjmp.S	18 Aug 2006 23:12:07 -0000
@@ -1,5 +1,5 @@
 /* longjmp for ARM.
-   Copyright (C) 1997, 1998, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -21,8 +21,6 @@
 #define _SETJMP_H
 #define _ASM
 #include <bits/setjmp.h>
-#define __ASSEMBLY__
-#include <asm/procinfo.h>
 #include <rtld-global-offsets.h>
 
 /* __longjmp(jmpbuf, val) */
@@ -53,7 +51,7 @@
 #endif
 #endif
 
-	tst	a2, #HWCAP_VFP
+	tst	a2, #HWCAP_ARM_VFP
 	beq	Lno_vfp
 
 	/* Restore the VFP registers.  */
@@ -65,6 +63,19 @@
 	mcr	p10, 7, r1, cr1, cr0, 0
 Lno_vfp:
 
+	tst	a2, #HWCAP_ARM_IWMMXT
+	beq	Lno_iwmmxt
+
+	/* Restore the call-preserved iWMMXt registers.  */
+	/* Following instructions are wldrd wr10, [ip], #8 (etc.)  */
+	ldcl	p1, cr10, [r12], #8
+	ldcl	p1, cr11, [r12], #8
+	ldcl	p1, cr12, [r12], #8
+	ldcl	p1, cr13, [r12], #8
+	ldcl	p1, cr14, [r12], #8
+	ldcl	p1, cr15, [r12], #8
+Lno_iwmmxt:
+
 	DO_RET(lr)
 
 #ifdef IS_IN_rtld
Index: sysdeps/arm/eabi/setjmp.S
===================================================================
RCS file: /cvs/glibc/ports/sysdeps/arm/eabi/setjmp.S,v
retrieving revision 1.1
diff -u -r1.1 setjmp.S
--- sysdeps/arm/eabi/setjmp.S	10 Oct 2005 15:29:32 -0000	1.1
+++ sysdeps/arm/eabi/setjmp.S	18 Aug 2006 23:12:07 -0000
@@ -1,5 +1,5 @@
 /* setjmp for ARM.
-   Copyright (C) 1997, 1998, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -21,8 +21,6 @@
 #define _SETJMP_H
 #define _ASM
 #include <bits/setjmp.h>
-#define __ASSEMBLY__
-#include <asm/procinfo.h>
 #include <rtld-global-offsets.h>
 
 ENTRY (__sigsetjmp)
@@ -51,7 +49,7 @@
 #endif
 #endif
 
-	tst	a3, #HWCAP_VFP
+	tst	a3, #HWCAP_ARM_VFP
 	beq	Lno_vfp
 
 	/* Store the VFP registers.  */
@@ -63,6 +61,19 @@
 	str	r2, [ip], #4
 Lno_vfp:
 
+	tst	a3, #HWCAP_ARM_IWMMXT
+	beq	Lno_iwmmxt
+
+	/* Save the call-preserved iWMMXt registers.  */
+	/* Following instructions are wstrd wr10, [ip], #8 (etc.)  */
+	stcl	p1, cr10, [r12], #8
+	stcl	p1, cr11, [r12], #8
+	stcl	p1, cr12, [r12], #8
+	stcl	p1, cr13, [r12], #8
+	stcl	p1, cr14, [r12], #8
+	stcl	p1, cr15, [r12], #8
+Lno_iwmmxt:
+
 	/* Make a tail call to __sigjmp_save; it takes the same args.  */
 	B	PLTJMP(C_SYMBOL_NAME(__sigjmp_save))
 
Index: sysdeps/unix/sysv/linux/arm/dl-procinfo.c
===================================================================
RCS file: /cvs/glibc/ports/sysdeps/unix/sysv/linux/arm/dl-procinfo.c,v
retrieving revision 1.5
diff -u -r1.5 dl-procinfo.c
--- sysdeps/unix/sysv/linux/arm/dl-procinfo.c	22 Jul 2003 22:07:18 -0000	1.5
+++ sysdeps/unix/sysv/linux/arm/dl-procinfo.c	18 Aug 2006 23:12:07 -0000
@@ -1,5 +1,5 @@
 /* Data for Linux/ARM version of processor capability information.
-   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Philip Blundell <philb@gnu.org>, 2001.
 
@@ -47,11 +47,12 @@
 #if !defined PROCINFO_DECL && defined SHARED
   ._dl_arm_cap_flags
 #else
-PROCINFO_CLASS const char _dl_arm_cap_flags[8][10]
+PROCINFO_CLASS const char _dl_arm_cap_flags[10][10]
 #endif
 #ifndef PROCINFO_DECL
 = {
     "swp", "half", "thumb", "26bit", "fast-mult", "fpa", "vfp", "edsp",
+    "java", "iwmmxt",
   }
 #endif
 #if !defined SHARED || defined PROCINFO_DECL
Index: sysdeps/unix/sysv/linux/arm/dl-procinfo.h
===================================================================
RCS file: /cvs/glibc/ports/sysdeps/unix/sysv/linux/arm/dl-procinfo.h,v
retrieving revision 1.5
diff -u -r1.5 dl-procinfo.h
--- sysdeps/unix/sysv/linux/arm/dl-procinfo.h	7 Mar 2004 08:38:42 -0000	1.5
+++ sysdeps/unix/sysv/linux/arm/dl-procinfo.h	18 Aug 2006 23:12:07 -0000
@@ -1,5 +1,5 @@
 /* Linux/ARM version of processor capability information handling macros.
-   Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Philip Blundell <philb@gnu.org>, 2001.
 
@@ -22,8 +22,9 @@
 #define _DL_PROCINFO_H	1
 
 #include <ldsodefs.h>
+#include <sysdep.h>
 
-#define _DL_HWCAP_COUNT 8
+#define _DL_HWCAP_COUNT 10
 
 /* The kernel provides platform data but it is not interesting.  */
 #define _DL_HWCAP_PLATFORM 	0
@@ -53,19 +54,7 @@
   return GLRO(dl_arm_cap_flags)[idx];
 };
 
-enum
-{
-  HWCAP_ARM_SWP	      = 1 << 0,
-  HWCAP_ARM_HALF      = 1 << 1,
-  HWCAP_ARM_THUMB     = 1 << 2,
-  HWCAP_ARM_26BIT     = 1 << 3,
-  HWCAP_ARM_FAST_MULT = 1 << 4,
-  HWCAP_ARM_FPA       = 1 << 5,
-  HWCAP_ARM_VFP       = 1 << 6,
-  HWCAP_ARM_EDSP      = 1 << 7,
-
-  HWCAP_IMPORTANT = (HWCAP_ARM_HALF | HWCAP_ARM_FAST_MULT)
-};
+#define HWCAP_IMPORTANT		(HWCAP_ARM_HALF | HWCAP_ARM_FAST_MULT)
 
 static inline int
 __attribute__ ((unused))
Index: sysdeps/unix/sysv/linux/arm/sysdep.h
===================================================================
RCS file: /cvs/glibc/ports/sysdeps/unix/sysv/linux/arm/sysdep.h,v
retrieving revision 1.30
diff -u -r1.30 sysdep.h
--- sysdeps/unix/sysv/linux/arm/sysdep.h	28 Feb 2006 19:26:36 -0000	1.30
+++ sysdeps/unix/sysv/linux/arm/sysdep.h	18 Aug 2006 23:12:07 -0000
@@ -37,6 +37,18 @@
 #define SYS_ify(syscall_name)	(__NR_##syscall_name)
 
 
+/* The following must match the kernel's <asm/procinfo.h>.  */
+#define HWCAP_ARM_SWP		1
+#define HWCAP_ARM_HALF		2
+#define HWCAP_ARM_THUMB		4
+#define HWCAP_ARM_26BIT		8
+#define HWCAP_ARM_FAST_MULT	16
+#define HWCAP_ARM_FPA		32
+#define HWCAP_ARM_VFP		64
+#define HWCAP_ARM_EDSP		128
+#define HWCAP_ARM_JAVA		256
+#define HWCAP_ARM_IWMMXT	512
+
 #ifdef __ASSEMBLER__
 
 /* Linux uses a negative return value to indicate syscall errors,


-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]