OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [gcc-4.5.1/] [gcc-4.5.1-or32-1.0rc2/] [gcc/] [config/] [rs6000/] [linux-unwind.h] - Diff between revs 282 and 384

Only display areas with differences | Details | Blame | View Log

Rev 282 Rev 384
/* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux.
/* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux.
   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 
   This file is part of GCC.
   This file is part of GCC.
 
 
   GCC is free software; you can redistribute it and/or modify it
   GCC is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published
   under the terms of the GNU General Public License as published
   by the Free Software Foundation; either version 3, or (at your
   by the Free Software Foundation; either version 3, or (at your
   option) any later version.
   option) any later version.
 
 
   GCC is distributed in the hope that it will be useful, but WITHOUT
   GCC is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   License for more details.
   License for more details.
 
 
   Under Section 7 of GPL version 3, you are granted additional
   Under Section 7 of GPL version 3, you are granted additional
   permissions described in the GCC Runtime Library Exception, version
   permissions described in the GCC Runtime Library Exception, version
   3.1, as published by the Free Software Foundation.
   3.1, as published by the Free Software Foundation.
 
 
   You should have received a copy of the GNU General Public License and
   You should have received a copy of the GNU General Public License and
   a copy of the GCC Runtime Library Exception along with this program;
   a copy of the GCC Runtime Library Exception along with this program;
   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
   <http://www.gnu.org/licenses/>.  */
   <http://www.gnu.org/licenses/>.  */
 
 
#define R_LR            65
#define R_LR            65
#define R_CR2           70
#define R_CR2           70
#define R_VR0           77
#define R_VR0           77
#define R_VRSAVE        109
#define R_VRSAVE        109
#define R_VSCR          110
#define R_VSCR          110
 
 
struct gcc_vregs
struct gcc_vregs
{
{
  __attribute__ ((vector_size (16))) int vr[32];
  __attribute__ ((vector_size (16))) int vr[32];
#ifdef __powerpc64__
#ifdef __powerpc64__
  unsigned int pad1[3];
  unsigned int pad1[3];
  unsigned int vscr;
  unsigned int vscr;
  unsigned int vsave;
  unsigned int vsave;
  unsigned int pad2[3];
  unsigned int pad2[3];
#else
#else
  unsigned int vsave;
  unsigned int vsave;
  unsigned int pad[2];
  unsigned int pad[2];
  unsigned int vscr;
  unsigned int vscr;
#endif
#endif
};
};
 
 
struct gcc_regs
struct gcc_regs
{
{
  unsigned long gpr[32];
  unsigned long gpr[32];
  unsigned long nip;
  unsigned long nip;
  unsigned long msr;
  unsigned long msr;
  unsigned long orig_gpr3;
  unsigned long orig_gpr3;
  unsigned long ctr;
  unsigned long ctr;
  unsigned long link;
  unsigned long link;
  unsigned long xer;
  unsigned long xer;
  unsigned long ccr;
  unsigned long ccr;
  unsigned long softe;
  unsigned long softe;
  unsigned long trap;
  unsigned long trap;
  unsigned long dar;
  unsigned long dar;
  unsigned long dsisr;
  unsigned long dsisr;
  unsigned long result;
  unsigned long result;
  unsigned long pad1[4];
  unsigned long pad1[4];
  double fpr[32];
  double fpr[32];
  unsigned int pad2;
  unsigned int pad2;
  unsigned int fpscr;
  unsigned int fpscr;
#ifdef __powerpc64__
#ifdef __powerpc64__
  struct gcc_vregs *vp;
  struct gcc_vregs *vp;
#else
#else
  unsigned int pad3[2];
  unsigned int pad3[2];
#endif
#endif
  struct gcc_vregs vregs;
  struct gcc_vregs vregs;
};
};
 
 
struct gcc_ucontext
struct gcc_ucontext
{
{
#ifdef __powerpc64__
#ifdef __powerpc64__
  unsigned long pad[28];
  unsigned long pad[28];
#else
#else
  unsigned long pad[12];
  unsigned long pad[12];
#endif
#endif
  struct gcc_regs *regs;
  struct gcc_regs *regs;
  struct gcc_regs rsave;
  struct gcc_regs rsave;
};
};
 
 
#ifdef __powerpc64__
#ifdef __powerpc64__
 
 
enum { SIGNAL_FRAMESIZE = 128 };
enum { SIGNAL_FRAMESIZE = 128 };
 
 
/* If PC is at a sigreturn trampoline, return a pointer to the
/* If PC is at a sigreturn trampoline, return a pointer to the
   regs.  Otherwise return NULL.  */
   regs.  Otherwise return NULL.  */
 
 
static struct gcc_regs *
static struct gcc_regs *
get_regs (struct _Unwind_Context *context)
get_regs (struct _Unwind_Context *context)
{
{
  const unsigned int *pc = context->ra;
  const unsigned int *pc = context->ra;
 
 
  /* addi r1, r1, 128; li r0, 0x0077; sc  (sigreturn) */
  /* addi r1, r1, 128; li r0, 0x0077; sc  (sigreturn) */
  /* addi r1, r1, 128; li r0, 0x00AC; sc  (rt_sigreturn) */
  /* addi r1, r1, 128; li r0, 0x00AC; sc  (rt_sigreturn) */
  if (pc[0] != 0x38210000 + SIGNAL_FRAMESIZE || pc[2] != 0x44000002)
  if (pc[0] != 0x38210000 + SIGNAL_FRAMESIZE || pc[2] != 0x44000002)
    return NULL;
    return NULL;
  if (pc[1] == 0x38000077)
  if (pc[1] == 0x38000077)
    {
    {
      struct sigframe {
      struct sigframe {
        char gap[SIGNAL_FRAMESIZE];
        char gap[SIGNAL_FRAMESIZE];
        unsigned long pad[7];
        unsigned long pad[7];
        struct gcc_regs *regs;
        struct gcc_regs *regs;
      } *frame = (struct sigframe *) context->cfa;
      } *frame = (struct sigframe *) context->cfa;
      return frame->regs;
      return frame->regs;
    }
    }
  else if (pc[1] == 0x380000AC)
  else if (pc[1] == 0x380000AC)
    {
    {
      /* This works for 2.4 kernels, but not for 2.6 kernels with vdso
      /* This works for 2.4 kernels, but not for 2.6 kernels with vdso
         because pc isn't pointing into the stack.  Can be removed when
         because pc isn't pointing into the stack.  Can be removed when
         no one is running 2.4.19 or 2.4.20, the first two ppc64
         no one is running 2.4.19 or 2.4.20, the first two ppc64
         kernels released.  */
         kernels released.  */
      const struct rt_sigframe_24 {
      const struct rt_sigframe_24 {
        int tramp[6];
        int tramp[6];
        void *pinfo;
        void *pinfo;
        struct gcc_ucontext *puc;
        struct gcc_ucontext *puc;
      } *frame24 = (const struct rt_sigframe_24 *) context->ra;
      } *frame24 = (const struct rt_sigframe_24 *) context->ra;
 
 
      /* Test for magic value in *puc of vdso.  */
      /* Test for magic value in *puc of vdso.  */
      if ((long) frame24->puc != -21 * 8)
      if ((long) frame24->puc != -21 * 8)
        return frame24->puc->regs;
        return frame24->puc->regs;
      else
      else
        {
        {
          /* This works for 2.4.21 and later kernels.  */
          /* This works for 2.4.21 and later kernels.  */
          struct rt_sigframe {
          struct rt_sigframe {
            char gap[SIGNAL_FRAMESIZE];
            char gap[SIGNAL_FRAMESIZE];
            struct gcc_ucontext uc;
            struct gcc_ucontext uc;
            unsigned long pad[2];
            unsigned long pad[2];
            int tramp[6];
            int tramp[6];
            void *pinfo;
            void *pinfo;
            struct gcc_ucontext *puc;
            struct gcc_ucontext *puc;
          } *frame = (struct rt_sigframe *) context->cfa;
          } *frame = (struct rt_sigframe *) context->cfa;
          return frame->uc.regs;
          return frame->uc.regs;
        }
        }
    }
    }
  return NULL;
  return NULL;
}
}
 
 
#else  /* !__powerpc64__ */
#else  /* !__powerpc64__ */
 
 
enum { SIGNAL_FRAMESIZE = 64 };
enum { SIGNAL_FRAMESIZE = 64 };
 
 
static struct gcc_regs *
static struct gcc_regs *
get_regs (struct _Unwind_Context *context)
get_regs (struct _Unwind_Context *context)
{
{
  const unsigned int *pc = context->ra;
  const unsigned int *pc = context->ra;
 
 
  /* li r0, 0x7777; sc  (sigreturn old)  */
  /* li r0, 0x7777; sc  (sigreturn old)  */
  /* li r0, 0x0077; sc  (sigreturn new)  */
  /* li r0, 0x0077; sc  (sigreturn new)  */
  /* li r0, 0x6666; sc  (rt_sigreturn old)  */
  /* li r0, 0x6666; sc  (rt_sigreturn old)  */
  /* li r0, 0x00AC; sc  (rt_sigreturn new)  */
  /* li r0, 0x00AC; sc  (rt_sigreturn new)  */
  if (pc[1] != 0x44000002)
  if (pc[1] != 0x44000002)
    return NULL;
    return NULL;
  if (pc[0] == 0x38007777 || pc[0] == 0x38000077)
  if (pc[0] == 0x38007777 || pc[0] == 0x38000077)
    {
    {
      struct sigframe {
      struct sigframe {
        char gap[SIGNAL_FRAMESIZE];
        char gap[SIGNAL_FRAMESIZE];
        unsigned long pad[7];
        unsigned long pad[7];
        struct gcc_regs *regs;
        struct gcc_regs *regs;
      } *frame = (struct sigframe *) context->cfa;
      } *frame = (struct sigframe *) context->cfa;
      return frame->regs;
      return frame->regs;
    }
    }
  else if (pc[0] == 0x38006666 || pc[0] == 0x380000AC)
  else if (pc[0] == 0x38006666 || pc[0] == 0x380000AC)
    {
    {
      struct rt_sigframe {
      struct rt_sigframe {
        char gap[SIGNAL_FRAMESIZE + 16];
        char gap[SIGNAL_FRAMESIZE + 16];
        char siginfo[128];
        char siginfo[128];
        struct gcc_ucontext uc;
        struct gcc_ucontext uc;
      } *frame = (struct rt_sigframe *) context->cfa;
      } *frame = (struct rt_sigframe *) context->cfa;
      return frame->uc.regs;
      return frame->uc.regs;
    }
    }
  return NULL;
  return NULL;
}
}
#endif
#endif
 
 
/* Find an entry in the process auxiliary vector.  The canonical way to
/* Find an entry in the process auxiliary vector.  The canonical way to
   test for VMX is to look at AT_HWCAP.  */
   test for VMX is to look at AT_HWCAP.  */
 
 
static long
static long
ppc_linux_aux_vector (long which)
ppc_linux_aux_vector (long which)
{
{
  /* __libc_stack_end holds the original stack passed to a process.  */
  /* __libc_stack_end holds the original stack passed to a process.  */
  extern long *__libc_stack_end;
  extern long *__libc_stack_end;
  long argc;
  long argc;
  char **argv;
  char **argv;
  char **envp;
  char **envp;
  struct auxv
  struct auxv
  {
  {
    long a_type;
    long a_type;
    long a_val;
    long a_val;
  } *auxp;
  } *auxp;
 
 
  /* The Linux kernel puts argc first on the stack.  */
  /* The Linux kernel puts argc first on the stack.  */
  argc = __libc_stack_end[0];
  argc = __libc_stack_end[0];
  /* Followed by argv, NULL terminated.  */
  /* Followed by argv, NULL terminated.  */
  argv = (char **) __libc_stack_end + 1;
  argv = (char **) __libc_stack_end + 1;
  /* Followed by environment string pointers, NULL terminated. */
  /* Followed by environment string pointers, NULL terminated. */
  envp = argv + argc + 1;
  envp = argv + argc + 1;
  while (*envp++)
  while (*envp++)
    continue;
    continue;
  /* Followed by the aux vector, zero terminated.  */
  /* Followed by the aux vector, zero terminated.  */
  for (auxp = (struct auxv *) envp; auxp->a_type != 0; ++auxp)
  for (auxp = (struct auxv *) envp; auxp->a_type != 0; ++auxp)
    if (auxp->a_type == which)
    if (auxp->a_type == which)
      return auxp->a_val;
      return auxp->a_val;
  return 0;
  return 0;
}
}
 
 
/* Do code reading to identify a signal frame, and set the frame
/* Do code reading to identify a signal frame, and set the frame
   state data appropriately.  See unwind-dw2.c for the structs.  */
   state data appropriately.  See unwind-dw2.c for the structs.  */
 
 
#define MD_FALLBACK_FRAME_STATE_FOR ppc_fallback_frame_state
#define MD_FALLBACK_FRAME_STATE_FOR ppc_fallback_frame_state
 
 
static _Unwind_Reason_Code
static _Unwind_Reason_Code
ppc_fallback_frame_state (struct _Unwind_Context *context,
ppc_fallback_frame_state (struct _Unwind_Context *context,
                          _Unwind_FrameState *fs)
                          _Unwind_FrameState *fs)
{
{
  static long hwcap = 0;
  static long hwcap = 0;
  struct gcc_regs *regs = get_regs (context);
  struct gcc_regs *regs = get_regs (context);
  long new_cfa;
  long new_cfa;
  int i;
  int i;
 
 
  if (regs == NULL)
  if (regs == NULL)
    return _URC_END_OF_STACK;
    return _URC_END_OF_STACK;
 
 
  new_cfa = regs->gpr[STACK_POINTER_REGNUM];
  new_cfa = regs->gpr[STACK_POINTER_REGNUM];
  fs->regs.cfa_how = CFA_REG_OFFSET;
  fs->regs.cfa_how = CFA_REG_OFFSET;
  fs->regs.cfa_reg = STACK_POINTER_REGNUM;
  fs->regs.cfa_reg = STACK_POINTER_REGNUM;
  fs->regs.cfa_offset = new_cfa - (long) context->cfa;
  fs->regs.cfa_offset = new_cfa - (long) context->cfa;
 
 
  for (i = 0; i < 32; i++)
  for (i = 0; i < 32; i++)
    if (i != STACK_POINTER_REGNUM)
    if (i != STACK_POINTER_REGNUM)
      {
      {
        fs->regs.reg[i].how = REG_SAVED_OFFSET;
        fs->regs.reg[i].how = REG_SAVED_OFFSET;
        fs->regs.reg[i].loc.offset = (long) &regs->gpr[i] - new_cfa;
        fs->regs.reg[i].loc.offset = (long) &regs->gpr[i] - new_cfa;
      }
      }
 
 
  fs->regs.reg[R_CR2].how = REG_SAVED_OFFSET;
  fs->regs.reg[R_CR2].how = REG_SAVED_OFFSET;
  /* CR? regs are always 32-bit and PPC is big-endian, so in 64-bit
  /* CR? regs are always 32-bit and PPC is big-endian, so in 64-bit
     libgcc loc.offset needs to point to the low 32 bits of regs->ccr.  */
     libgcc loc.offset needs to point to the low 32 bits of regs->ccr.  */
  fs->regs.reg[R_CR2].loc.offset = (long) &regs->ccr - new_cfa
  fs->regs.reg[R_CR2].loc.offset = (long) &regs->ccr - new_cfa
                                   + sizeof (long) - 4;
                                   + sizeof (long) - 4;
 
 
  fs->regs.reg[R_LR].how = REG_SAVED_OFFSET;
  fs->regs.reg[R_LR].how = REG_SAVED_OFFSET;
  fs->regs.reg[R_LR].loc.offset = (long) &regs->link - new_cfa;
  fs->regs.reg[R_LR].loc.offset = (long) &regs->link - new_cfa;
 
 
  fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET;
  fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET;
  fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) &regs->nip - new_cfa;
  fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) &regs->nip - new_cfa;
  fs->retaddr_column = ARG_POINTER_REGNUM;
  fs->retaddr_column = ARG_POINTER_REGNUM;
  fs->signal_frame = 1;
  fs->signal_frame = 1;
 
 
  if (hwcap == 0)
  if (hwcap == 0)
    {
    {
      hwcap = ppc_linux_aux_vector (16);
      hwcap = ppc_linux_aux_vector (16);
      /* These will already be set if we found AT_HWCAP.  A nonzero
      /* These will already be set if we found AT_HWCAP.  A nonzero
         value stops us looking again if for some reason we couldn't
         value stops us looking again if for some reason we couldn't
         find AT_HWCAP.  */
         find AT_HWCAP.  */
#ifdef __powerpc64__
#ifdef __powerpc64__
      hwcap |= 0xc0000000;
      hwcap |= 0xc0000000;
#else
#else
      hwcap |= 0x80000000;
      hwcap |= 0x80000000;
#endif
#endif
    }
    }
 
 
  /* If we have a FPU...  */
  /* If we have a FPU...  */
  if (hwcap & 0x08000000)
  if (hwcap & 0x08000000)
    for (i = 0; i < 32; i++)
    for (i = 0; i < 32; i++)
      {
      {
        fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
        fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
        fs->regs.reg[i + 32].loc.offset = (long) &regs->fpr[i] - new_cfa;
        fs->regs.reg[i + 32].loc.offset = (long) &regs->fpr[i] - new_cfa;
      }
      }
 
 
  /* If we have a VMX unit...  */
  /* If we have a VMX unit...  */
  if (hwcap & 0x10000000)
  if (hwcap & 0x10000000)
    {
    {
      struct gcc_vregs *vregs;
      struct gcc_vregs *vregs;
#ifdef __powerpc64__
#ifdef __powerpc64__
      vregs = regs->vp;
      vregs = regs->vp;
#else
#else
      vregs = &regs->vregs;
      vregs = &regs->vregs;
#endif
#endif
      if (regs->msr & (1 << 25))
      if (regs->msr & (1 << 25))
        {
        {
          for (i = 0; i < 32; i++)
          for (i = 0; i < 32; i++)
            {
            {
              fs->regs.reg[i + R_VR0].how = REG_SAVED_OFFSET;
              fs->regs.reg[i + R_VR0].how = REG_SAVED_OFFSET;
              fs->regs.reg[i + R_VR0].loc.offset
              fs->regs.reg[i + R_VR0].loc.offset
                = (long) &vregs->vr[i] - new_cfa;
                = (long) &vregs->vr[i] - new_cfa;
            }
            }
 
 
          fs->regs.reg[R_VSCR].how = REG_SAVED_OFFSET;
          fs->regs.reg[R_VSCR].how = REG_SAVED_OFFSET;
          fs->regs.reg[R_VSCR].loc.offset = (long) &vregs->vscr - new_cfa;
          fs->regs.reg[R_VSCR].loc.offset = (long) &vregs->vscr - new_cfa;
        }
        }
 
 
      fs->regs.reg[R_VRSAVE].how = REG_SAVED_OFFSET;
      fs->regs.reg[R_VRSAVE].how = REG_SAVED_OFFSET;
      fs->regs.reg[R_VRSAVE].loc.offset = (long) &vregs->vsave - new_cfa;
      fs->regs.reg[R_VRSAVE].loc.offset = (long) &vregs->vsave - new_cfa;
    }
    }
 
 
  /* If we have SPE register high-parts... we check at compile-time to
  /* If we have SPE register high-parts... we check at compile-time to
     avoid expanding the code for all other PowerPC.  */
     avoid expanding the code for all other PowerPC.  */
#ifdef __SPE__
#ifdef __SPE__
  for (i = 0; i < 32; i++)
  for (i = 0; i < 32; i++)
    {
    {
      fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].how = REG_SAVED_OFFSET;
      fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].how = REG_SAVED_OFFSET;
      fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].loc.offset
      fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].loc.offset
        = (long) &regs->vregs - new_cfa + 4 * i;
        = (long) &regs->vregs - new_cfa + 4 * i;
    }
    }
#endif
#endif
 
 
  return _URC_NO_REASON;
  return _URC_NO_REASON;
}
}
 
 
#define MD_FROB_UPDATE_CONTEXT frob_update_context
#define MD_FROB_UPDATE_CONTEXT frob_update_context
 
 
static void
static void
frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATTRIBUTE_UNUSED)
frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATTRIBUTE_UNUSED)
{
{
  const unsigned int *pc = (const unsigned int *) context->ra;
  const unsigned int *pc = (const unsigned int *) context->ra;
 
 
  /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't
  /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't
     have S flag in it.  */
     have S flag in it.  */
#ifdef __powerpc64__
#ifdef __powerpc64__
  /* addi r1, r1, 128; li r0, 0x0077; sc  (sigreturn) */
  /* addi r1, r1, 128; li r0, 0x0077; sc  (sigreturn) */
  /* addi r1, r1, 128; li r0, 0x00AC; sc  (rt_sigreturn) */
  /* addi r1, r1, 128; li r0, 0x00AC; sc  (rt_sigreturn) */
  if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE
  if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE
      && (pc[1] == 0x38000077 || pc[1] == 0x380000AC)
      && (pc[1] == 0x38000077 || pc[1] == 0x380000AC)
      && pc[2] == 0x44000002)
      && pc[2] == 0x44000002)
    _Unwind_SetSignalFrame (context, 1);
    _Unwind_SetSignalFrame (context, 1);
#else
#else
  /* li r0, 0x7777; sc  (sigreturn old)  */
  /* li r0, 0x7777; sc  (sigreturn old)  */
  /* li r0, 0x0077; sc  (sigreturn new)  */
  /* li r0, 0x0077; sc  (sigreturn new)  */
  /* li r0, 0x6666; sc  (rt_sigreturn old)  */
  /* li r0, 0x6666; sc  (rt_sigreturn old)  */
  /* li r0, 0x00AC; sc  (rt_sigreturn new)  */
  /* li r0, 0x00AC; sc  (rt_sigreturn new)  */
  if ((pc[0] == 0x38007777 || pc[0] == 0x38000077
  if ((pc[0] == 0x38007777 || pc[0] == 0x38000077
       || pc[0] == 0x38006666 || pc[0] == 0x380000AC)
       || pc[0] == 0x38006666 || pc[0] == 0x380000AC)
      && pc[1] == 0x44000002)
      && pc[1] == 0x44000002)
    _Unwind_SetSignalFrame (context, 1);
    _Unwind_SetSignalFrame (context, 1);
#endif
#endif
 
 
#ifdef __powerpc64__
#ifdef __powerpc64__
  if (fs->regs.reg[2].how == REG_UNSAVED)
  if (fs->regs.reg[2].how == REG_UNSAVED)
    {
    {
      /* If the current unwind info (FS) does not contain explicit info
      /* If the current unwind info (FS) does not contain explicit info
         saving R2, then we have to do a minor amount of code reading to
         saving R2, then we have to do a minor amount of code reading to
         figure out if it was saved.  The big problem here is that the
         figure out if it was saved.  The big problem here is that the
         code that does the save/restore is generated by the linker, so
         code that does the save/restore is generated by the linker, so
         we have no good way to determine at compile time what to do.  */
         we have no good way to determine at compile time what to do.  */
      unsigned int *insn
      unsigned int *insn
        = (unsigned int *) _Unwind_GetGR (context, R_LR);
        = (unsigned int *) _Unwind_GetGR (context, R_LR);
      if (insn && *insn == 0xE8410028)
      if (insn && *insn == 0xE8410028)
        _Unwind_SetGRPtr (context, 2, context->cfa + 40);
        _Unwind_SetGRPtr (context, 2, context->cfa + 40);
    }
    }
#endif
#endif
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.