(root)/
gcc-13.2.0/
libgcc/
config/
m68k/
linux-unwind.h
       1  /* DWARF2 EH unwinding support for Linux/m68k.
       2     Copyright (C) 2006-2023 Free Software Foundation, Inc.
       3  
       4  This file is part of GCC.
       5  
       6  GCC is free software; you can redistribute it and/or modify
       7  it under the terms of the GNU General Public License as published by
       8  the Free Software Foundation; either version 3, or (at your option)
       9  any later version.
      10  
      11  GCC is distributed in the hope that it will be useful,
      12  but WITHOUT ANY WARRANTY; without even the implied warranty of
      13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14  GNU General Public License for more details.
      15  
      16  Under Section 7 of GPL version 3, you are granted additional
      17  permissions described in the GCC Runtime Library Exception, version
      18  3.1, as published by the Free Software Foundation.
      19  
      20  You should have received a copy of the GNU General Public License and
      21  a copy of the GCC Runtime Library Exception along with this program;
      22  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      23  <http://www.gnu.org/licenses/>.  */
      24  
      25  /* Do code reading to identify a signal frame, and set the frame
      26     state data appropriately.  See unwind-dw2.c for the structs.
      27     Don't use this at all if inhibit_libc is used.  */
      28  
      29  #ifndef inhibit_libc
      30  
      31  #include <signal.h>
      32  
      33  /* <sys/ucontext.h> is unfortunately broken right now.  */
      34  struct uw_ucontext {
      35  	unsigned long	  uc_flags;
      36  	ucontext_t	 *uc_link;
      37  	stack_t		  uc_stack;
      38  	mcontext_t	  uc_mcontext;
      39  	unsigned long	  uc_filler[80];
      40  	sigset_t	  uc_sigmask;
      41  };
      42  
      43  #define MD_FALLBACK_FRAME_STATE_FOR m68k_fallback_frame_state
      44  
      45  #ifdef __mcoldfire__
      46  #define M68K_FP_SIZE  8
      47  #else
      48  #define M68K_FP_SIZE  12
      49  #endif
      50  
      51  static _Unwind_Reason_Code
      52  m68k_fallback_frame_state (struct _Unwind_Context *context,
      53  			   _Unwind_FrameState *fs)
      54  {
      55    unsigned short *pc = context->ra;
      56    long cfa;
      57  
      58    /* moveq #__NR_sigreturn,%d0; trap #0  */
      59    if (pc[0] == 0x7077 && pc[1] == 0x4e40)
      60      {
      61        struct sigcontext *sc;
      62  
      63        /* Context is passed as the 3rd argument.  */
      64        sc = *(struct sigcontext **) (context->cfa + 8);
      65  
      66        cfa = sc->sc_usp;
      67        fs->regs.cfa_how = CFA_REG_OFFSET;
      68        fs->regs.cfa_reg = 15;
      69        fs->regs.cfa_offset = cfa - (long) context->cfa;
      70  
      71        fs->regs.how[0] = REG_SAVED_OFFSET;
      72        fs->regs.reg[0].loc.offset = (long) &sc->sc_d0 - cfa;
      73        fs->regs.how[1] = REG_SAVED_OFFSET;
      74        fs->regs.reg[1].loc.offset = (long) &sc->sc_d1 - cfa;
      75        fs->regs.how[8] = REG_SAVED_OFFSET;
      76        fs->regs.reg[8].loc.offset = (long) &sc->sc_a0 - cfa;
      77        fs->regs.how[9] = REG_SAVED_OFFSET;
      78        fs->regs.reg[9].loc.offset = (long) &sc->sc_a1 - cfa;
      79  
      80  #ifdef __uClinux__
      81        fs->regs.how[13] = REG_SAVED_OFFSET;
      82        fs->regs.reg[13].loc.offset = (long) &sc->sc_a5 - cfa;
      83  #endif
      84  
      85        fs->regs.how[24] = REG_SAVED_OFFSET;
      86        fs->regs.reg[24].loc.offset = (long) &sc->sc_pc - cfa;
      87  
      88  #ifndef __uClinux__
      89        if (*(int *) sc->sc_fpstate)
      90  	{
      91  	  int *fpregs = (int *) sc->sc_fpregs;
      92  
      93  	  fs->regs.how[16] = REG_SAVED_OFFSET;
      94  	  fs->regs.reg[16].loc.offset = (long) &fpregs[0] - cfa;
      95  	  fs->regs.how[17] = REG_SAVED_OFFSET;
      96  	  fs->regs.reg[17].loc.offset = (long) &fpregs[M68K_FP_SIZE/4] - cfa;
      97  	}
      98  #elif defined __mcffpu__
      99  # error Implement this when uClinux kernel is ported to an FPU architecture
     100  #endif
     101      }
     102  #ifdef __mcoldfire__
     103    /* move.l #__NR_rt_sigreturn,%d0; trap #0 */
     104    else if (pc[0] == 0x203c && pc[1] == 0x0000 &&
     105  	   pc[2] == 0x00ad && pc[3] == 0x4e40)
     106  #else
     107    /* moveq #~__NR_rt_sigreturn,%d0; not.b %d0; trap #0 */
     108    else if (pc[0] == 0x7052 && pc[1] == 0x4600 && pc[2] == 0x4e40)
     109  #endif
     110      {
     111        struct uw_ucontext *uc;
     112        greg_t *gregs;
     113        int i;
     114  
     115        /* Context is passed as the 3rd argument.  */
     116        uc = *(struct uw_ucontext **) (context->cfa + 8);
     117  
     118        gregs = uc->uc_mcontext.gregs;
     119        cfa = gregs[15];
     120        fs->regs.cfa_how = CFA_REG_OFFSET;
     121        fs->regs.cfa_reg = 15;
     122        fs->regs.cfa_offset = cfa - (long) context->cfa;
     123  
     124        /* register %d0-%d7/%a0-%a6  */
     125        for (i = 0; i <= 14; i++)
     126  	{
     127  	  fs->regs.how[i] = REG_SAVED_OFFSET;
     128  	  fs->regs.reg[i].loc.offset = (long) &gregs[i] - cfa;
     129  	}
     130  
     131        /* return address  */
     132        fs->regs.how[24] = REG_SAVED_OFFSET;
     133        fs->regs.reg[24].loc.offset = (long) &gregs[16] - cfa;
     134  
     135  #define uc_fpstate      uc_filler[0]
     136  
     137        if (uc->uc_fpstate)
     138  	{
     139  	  long fpregs = (long) uc->uc_mcontext.fpregs.f_fpregs;
     140  
     141  	  /* register %fp0-%fp7  */
     142  	  for (i = 16; i <= 23; i++)
     143  	    {
     144  	      fs->regs.how[i] = REG_SAVED_OFFSET;
     145  	      fs->regs.reg[i].loc.offset = fpregs - cfa;
     146  	      fpregs += M68K_FP_SIZE;
     147  	    }
     148  	}
     149      }
     150    else
     151      return _URC_END_OF_STACK;
     152  
     153    fs->retaddr_column = 24;
     154    fs->signal_frame = 1;
     155  
     156    return _URC_NO_REASON;
     157  }
     158  #endif /* ifdef inhibit_libc  */