libunwind.S: Add .arch/.object_arch for armv4 builds.

gcc:
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.

From-SVN: r122658
This commit is contained in:
Joseph Myers 2007-03-07 13:04:15 +00:00
parent ef67275542
commit a566d05002
5 changed files with 240 additions and 2 deletions

View 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.

View File

@ -41,6 +41,18 @@
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

View 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,10 +446,81 @@ _Unwind_VRS_Result _Unwind_VRS_Pop (_Unwind_Context *context,
return _UVRSR_OK;
case _UVRSC_FPA:
case _UVRSC_WMMXD:
case _UVRSC_WMMXC:
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:
{
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;
}

View 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.

View File

@ -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