gcc:
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 7 Mar 2007 13:04:15 +0000 (13:04 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 7 Mar 2007 13:04:15 +0000 (13:04 +0000)
2007-03-07  Paul Brook  <paul@codesourcery.com>

* config/arm/libunwind.S: Add .arch/.object_arch for armv4 builds.

gcc:
2007-03-07  Joseph Myers  <joseph@codesourcery.com>

* config/arm/unwind-arm.c (struct wmmxd_regs, struct wmmxc_regs):
New.
(phase1_vrs): Use them.
(DEMAND_SAVE_WMMXD, DEMAND_SAVE_WMMXC): New.
(__gnu_Unwind_Save_WMMXD, __gnu_Unwind_Restore_WMMXD,
__gnu_Unwind_Save_WMMXC, __gnu_Unwind_Restore_WMMXC): Declare.
(restore_non_core_regs): Call __gnu_Unwind_Restore_WMMXD and
__gnu_Unwind_Restore_WMMXC if required.
(_Unwind_VRS_Pop): Implement iWMMXt support.
* config/arm/libunwind.S (gnu_Unwind_Restore_WMMXD,
gnu_Unwind_Save_WMMXD, gnu_Unwind_Restore_WMMXC,
gnu_Unwind_Save_WMMXC): Define.

gcc/testsuite:
2007-03-07  Joseph Myers  <joseph@codesourcery.com>

* g++.dg/eh/arm-iwmmxt-unwind.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122658 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/libunwind.S
gcc/config/arm/unwind-arm.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/eh/arm-iwmmxt-unwind.C [new file with mode: 0644]

index d4ae2b5..4f61c94 100644 (file)
@@ -1,3 +1,22 @@
+2007-03-07  Paul Brook  <paul@codesourcery.com>
+
+       * config/arm/libunwind.S: Add .arch/.object_arch for armv4 builds.
+
+2007-03-07  Joseph Myers  <joseph@codesourcery.com>
+
+       * config/arm/unwind-arm.c (struct wmmxd_regs, struct wmmxc_regs):
+       New.
+       (phase1_vrs): Use them.
+       (DEMAND_SAVE_WMMXD, DEMAND_SAVE_WMMXC): New.
+       (__gnu_Unwind_Save_WMMXD, __gnu_Unwind_Restore_WMMXD,
+       __gnu_Unwind_Save_WMMXC, __gnu_Unwind_Restore_WMMXC): Declare.
+       (restore_non_core_regs): Call __gnu_Unwind_Restore_WMMXD and
+       __gnu_Unwind_Restore_WMMXC if required.
+       (_Unwind_VRS_Pop): Implement iWMMXt support.
+       * config/arm/libunwind.S (gnu_Unwind_Restore_WMMXD,
+       gnu_Unwind_Save_WMMXD, gnu_Unwind_Restore_WMMXC,
+       gnu_Unwind_Save_WMMXC): Define.
+
 2007-03-07  Richard Sandiford  <richard@codesourcery.com>
 
        * config/vxworks.h (vxworks_override_options): Declare.
index ef3f89a..2328471 100644 (file)
        EQUIV SYM (\name), SYM (__\name)
 .endm
 
+#if (__ARM_ARCH__ == 4)
+/* Some coprocessors require armv5.  We know this code will never be run on
+   other cpus.  Tell gas to allow armv5, but only mark the objects as armv4.
+ */
+.arch armv5t
+#ifdef __ARM_ARCH_4T__
+.object_arch armv4t
+#else
+.object_arch armv4
+#endif
+#endif
+
 /* r0 points to a 16-word block.  Upload these values to the actual core
    state.  */
 ARM_FUNC_START restore_core_regs
@@ -119,6 +131,66 @@ ARM_FUNC_START gnu_Unwind_Save_VFP_D_16_to_31
        stcl  p11,cr0,[r0],{0x20} /* vstm r0, {d16-d31} */
        RET
 
+ARM_FUNC_START gnu_Unwind_Restore_WMMXD
+       /* Use the generic coprocessor form so that gas doesn't complain
+          on non-iWMMXt targets.  */
+       ldcl  p1, cr0, [r0], #8 /* wldrd wr0, [r0], #8 */
+       ldcl  p1, cr1, [r0], #8 /* wldrd wr1, [r0], #8 */
+       ldcl  p1, cr2, [r0], #8 /* wldrd wr2, [r0], #8 */
+       ldcl  p1, cr3, [r0], #8 /* wldrd wr3, [r0], #8 */
+       ldcl  p1, cr4, [r0], #8 /* wldrd wr4, [r0], #8 */
+       ldcl  p1, cr5, [r0], #8 /* wldrd wr5, [r0], #8 */
+       ldcl  p1, cr6, [r0], #8 /* wldrd wr6, [r0], #8 */
+       ldcl  p1, cr7, [r0], #8 /* wldrd wr7, [r0], #8 */
+       ldcl  p1, cr8, [r0], #8 /* wldrd wr8, [r0], #8 */
+       ldcl  p1, cr9, [r0], #8 /* wldrd wr9, [r0], #8 */
+       ldcl  p1, cr10, [r0], #8 /* wldrd wr10, [r0], #8 */
+       ldcl  p1, cr11, [r0], #8 /* wldrd wr11, [r0], #8 */
+       ldcl  p1, cr12, [r0], #8 /* wldrd wr12, [r0], #8 */
+       ldcl  p1, cr13, [r0], #8 /* wldrd wr13, [r0], #8 */
+       ldcl  p1, cr14, [r0], #8 /* wldrd wr14, [r0], #8 */
+       ldcl  p1, cr15, [r0], #8 /* wldrd wr15, [r0], #8 */
+       RET
+
+ARM_FUNC_START gnu_Unwind_Save_WMMXD
+       /* Use the generic coprocessor form so that gas doesn't complain
+          on non-iWMMXt targets.  */
+       stcl  p1, cr0, [r0], #8 /* wstrd wr0, [r0], #8 */
+       stcl  p1, cr1, [r0], #8 /* wstrd wr1, [r0], #8 */
+       stcl  p1, cr2, [r0], #8 /* wstrd wr2, [r0], #8 */
+       stcl  p1, cr3, [r0], #8 /* wstrd wr3, [r0], #8 */
+       stcl  p1, cr4, [r0], #8 /* wstrd wr4, [r0], #8 */
+       stcl  p1, cr5, [r0], #8 /* wstrd wr5, [r0], #8 */
+       stcl  p1, cr6, [r0], #8 /* wstrd wr6, [r0], #8 */
+       stcl  p1, cr7, [r0], #8 /* wstrd wr7, [r0], #8 */
+       stcl  p1, cr8, [r0], #8 /* wstrd wr8, [r0], #8 */
+       stcl  p1, cr9, [r0], #8 /* wstrd wr9, [r0], #8 */
+       stcl  p1, cr10, [r0], #8 /* wstrd wr10, [r0], #8 */
+       stcl  p1, cr11, [r0], #8 /* wstrd wr11, [r0], #8 */
+       stcl  p1, cr12, [r0], #8 /* wstrd wr12, [r0], #8 */
+       stcl  p1, cr13, [r0], #8 /* wstrd wr13, [r0], #8 */
+       stcl  p1, cr14, [r0], #8 /* wstrd wr14, [r0], #8 */
+       stcl  p1, cr15, [r0], #8 /* wstrd wr15, [r0], #8 */
+       RET
+
+ARM_FUNC_START gnu_Unwind_Restore_WMMXC
+       /* Use the generic coprocessor form so that gas doesn't complain
+          on non-iWMMXt targets.  */
+       ldc2  p1, cr8, [r0], #4 /* wldrw wcgr0, [r0], #4 */
+       ldc2  p1, cr9, [r0], #4 /* wldrw wcgr1, [r0], #4 */
+       ldc2  p1, cr10, [r0], #4 /* wldrw wcgr2, [r0], #4 */
+       ldc2  p1, cr11, [r0], #4 /* wldrw wcgr3, [r0], #4 */
+       RET
+
+ARM_FUNC_START gnu_Unwind_Save_WMMXC
+       /* Use the generic coprocessor form so that gas doesn't complain
+          on non-iWMMXt targets.  */
+       stc2  p1, cr8, [r0], #4 /* wstrw wcgr0, [r0], #4 */
+       stc2  p1, cr9, [r0], #4 /* wstrw wcgr1, [r0], #4 */
+       stc2  p1, cr10, [r0], #4 /* wstrw wcgr2, [r0], #4 */
+       stc2  p1, cr11, [r0], #4 /* wstrw wcgr3, [r0], #4 */
+       RET
+
 /* Wrappers to save core registers, then call the real routine.   */
 
 .macro  UNWIND_WRAPPER name nargs
index 4b75b0f..60f61d5 100644 (file)
@@ -91,6 +91,16 @@ struct fpa_regs
   struct fpa_reg f[8];
 };
 
+struct wmmxd_regs
+{
+  _uw64 wd[16];
+};
+
+struct wmmxc_regs
+{
+  _uw wc[4];
+};
+
 /* Unwind descriptors.  */
 
 typedef struct
@@ -123,12 +133,18 @@ typedef struct
   struct vfp_regs vfp;
   struct vfpv3_regs vfp_regs_16_to_31;
   struct fpa_regs fpa;
+  struct wmmxd_regs wmmxd;
+  struct wmmxc_regs wmmxc;
 } phase1_vrs;
 
 #define DEMAND_SAVE_VFP 1      /* VFP state has been saved if not set */
 #define DEMAND_SAVE_VFP_D 2    /* VFP state is for FLDMD/FSTMD if set */
 #define DEMAND_SAVE_VFP_V3 4    /* VFPv3 state for regs 16 .. 31 has
                                    been saved if not set */
+#define DEMAND_SAVE_WMMXD 8    /* iWMMXt data registers have been
+                                  saved if not set.  */
+#define DEMAND_SAVE_WMMXC 16   /* iWMMXt control registers have been
+                                  saved if not set.  */
 
 /* This must match the structure created by the assembly wrappers.  */
 typedef struct
@@ -157,6 +173,10 @@ void __attribute__((noreturn)) restore_core_regs (struct core_regs *);
 /* Routines for FLDMX/FSTMX format...  */
 void __gnu_Unwind_Save_VFP (struct vfp_regs * p);
 void __gnu_Unwind_Restore_VFP (struct vfp_regs * p);
+void __gnu_Unwind_Save_WMMXD (struct wmmxd_regs * p);
+void __gnu_Unwind_Restore_WMMXD (struct wmmxd_regs * p);
+void __gnu_Unwind_Save_WMMXC (struct wmmxc_regs * p);
+void __gnu_Unwind_Restore_WMMXC (struct wmmxc_regs * p);
 
 /* ...and those for FLDMD/FSTMD format...  */
 void __gnu_Unwind_Save_VFP_D (struct vfp_regs * p);
@@ -181,6 +201,11 @@ restore_non_core_regs (phase1_vrs * vrs)
 
   if ((vrs->demand_save_flags & DEMAND_SAVE_VFP_V3) == 0)
     __gnu_Unwind_Restore_VFP_D_16_to_31 (&vrs->vfp_regs_16_to_31);
+
+  if ((vrs->demand_save_flags & DEMAND_SAVE_WMMXD) == 0)
+    __gnu_Unwind_Restore_WMMXD (&vrs->wmmxd);
+  if ((vrs->demand_save_flags & DEMAND_SAVE_WMMXC) == 0)
+    __gnu_Unwind_Restore_WMMXC (&vrs->wmmxc);
 }
 
 /* A better way to do this would probably be to compare the absolute address
@@ -421,9 +446,80 @@ _Unwind_VRS_Result _Unwind_VRS_Pop (_Unwind_Context *context,
       return _UVRSR_OK;
 
     case _UVRSC_FPA:
+      return _UVRSR_NOT_IMPLEMENTED;
+
     case _UVRSC_WMMXD:
+      {
+       _uw start = discriminator >> 16;
+       _uw count = discriminator & 0xffff;
+       struct wmmxd_regs tmp;
+       _uw *sp;
+       _uw *dest;
+
+       if ((representation != _UVRSD_UINT64) || start + count > 16)
+         return _UVRSR_FAILED;
+
+       if (vrs->demand_save_flags & DEMAND_SAVE_WMMXD)
+         {
+           /* Demand-save resisters for stage1.  */
+           vrs->demand_save_flags &= ~DEMAND_SAVE_WMMXD;
+           __gnu_Unwind_Save_WMMXD (&vrs->wmmxd);
+         }
+
+       /* Restore the registers from the stack.  Do this by saving the
+          current WMMXD registers to a memory area, moving the in-memory
+          values into that area, and restoring from the whole area.  */
+       __gnu_Unwind_Save_WMMXD (&tmp);
+
+       /* The stack address is only guaranteed to be word aligned, so
+          we can't use doubleword copies.  */
+       sp = (_uw *) vrs->core.r[R_SP];
+       dest = (_uw *) &tmp.wd[start];
+       count *= 2;
+       while (count--)
+         *(dest++) = *(sp++);
+
+       /* Set the new stack pointer.  */
+       vrs->core.r[R_SP] = (_uw) sp;
+
+       /* Reload the registers.  */
+       __gnu_Unwind_Restore_WMMXD (&tmp);
+      }
+      return _UVRSR_OK;
+
     case _UVRSC_WMMXC:
-      return _UVRSR_NOT_IMPLEMENTED;
+      {
+       int i;
+       struct wmmxc_regs tmp;
+       _uw *sp;
+
+       if ((representation != _UVRSD_UINT32) || discriminator > 16)
+         return _UVRSR_FAILED;
+
+       if (vrs->demand_save_flags & DEMAND_SAVE_WMMXC)
+         {
+           /* Demand-save resisters for stage1.  */
+           vrs->demand_save_flags &= ~DEMAND_SAVE_WMMXC;
+           __gnu_Unwind_Save_WMMXC (&vrs->wmmxc);
+         }
+
+       /* Restore the registers from the stack.  Do this by saving the
+          current WMMXC registers to a memory area, moving the in-memory
+          values into that area, and restoring from the whole area.  */
+       __gnu_Unwind_Save_WMMXC (&tmp);
+
+       sp = (_uw *) vrs->core.r[R_SP];
+       for (i = 0; i < 4; i++)
+         if (discriminator & (1 << i))
+           tmp.wc[i] = *(sp++);
+
+       /* Set the new stack pointer.  */
+       vrs->core.r[R_SP] = (_uw) sp;
+
+       /* Reload the registers.  */
+       __gnu_Unwind_Restore_WMMXC (&tmp);
+      }
+      return _UVRSR_OK;
 
     default:
       return _UVRSR_FAILED;
index 99fcde6..7d2b323 100644 (file)
@@ -1,3 +1,7 @@
+2007-03-07  Joseph Myers  <joseph@codesourcery.com>
+
+       * g++.dg/eh/arm-iwmmxt-unwind.C: New test.
+
 2007-03-07  Paolo Bonzini  <bonzini@gnu.org>
 
        * gcc.dg/var-expand1.c: Add newline at end of file.
diff --git a/gcc/testsuite/g++.dg/eh/arm-iwmmxt-unwind.C b/gcc/testsuite/g++.dg/eh/arm-iwmmxt-unwind.C
new file mode 100644 (file)
index 0000000..109837c
--- /dev/null
@@ -0,0 +1,47 @@
+/* Test unwinding of iWMMXt register saves.  */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm32 } */
+
+#ifdef __IWMMXT__
+extern "C" void abort (void);
+extern "C" void exit (int);
+
+void
+foo (void)
+{
+  register long long wr10 asm("wr10") = 0;
+  register long long wr11 asm("wr11") = 1;
+  register long long wr12 asm("wr12") = 2;
+  register long long wr14 asm("wr14") = 4;
+  register long long wr15 asm("wr15") = 5;
+  asm volatile ("" : "+y" (wr10), "+y" (wr11), "+y" (wr12), "+y" (wr14), "+y" (wr15));
+  throw "";
+}
+
+int
+main (void)
+{
+  register long long wr10 asm("wr10") = 10;
+  register long long wr11 asm("wr11") = 11;
+  register long long wr12 asm("wr12") = 12;
+  register long long wr13 asm("wr13") = 13;
+  register long long wr14 asm("wr14") = 14;
+  register long long wr15 asm("wr15") = 15;
+  asm volatile ("" : "+y" (wr10), "+y" (wr11), "+y" (wr12), "+y" (wr13), "+y" (wr14), "+y" (wr15));
+  try {
+    foo ();
+  } catch (...) {
+    asm volatile ("" : "+y" (wr10), "+y" (wr11), "+y" (wr12), "+y" (wr13), "+y" (wr14), "+y" (wr15));
+    if (wr10 != 10 || wr11 != 11 || wr12 != 12 || wr13 != 13 || wr14 != 14 || wr15 != 15)
+      abort ();
+  }
+  exit (0);
+}
+#else
+int
+main (void)
+{
+}
+#endif