ARM setjmp/longjmp support for iWMMXt

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

ARM setjmp/longjmp support for iWMMXt

Joseph Myers
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  <[hidden email]>

        * 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 <[hidden email]>, 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 <[hidden email]>, 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
[hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: ARM setjmp/longjmp support for iWMMXt

Daniel Jacobowitz-2
On Fri, Aug 18, 2006 at 11:13:41PM +0000, Joseph S. Myers wrote:

> 2006-08-18  Joseph Myers  <[hidden email]>
>
> * 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.

Thanks, checked in.

--
Daniel Jacobowitz
CodeSourcery