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:
parent
ef67275542
commit
a566d05002
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
47
gcc/testsuite/g++.dg/eh/arm-iwmmxt-unwind.C
Normal file
47
gcc/testsuite/g++.dg/eh/arm-iwmmxt-unwind.C
Normal 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
|
Loading…
Reference in New Issue
Block a user