181418a27Smrg /* DWARF2 EH unwinding support for OpenRISC Linux.
2*8d286336Smrg    Copyright (C) 2018-2020 Free Software Foundation, Inc.
362a470c0Smatt 
462a470c0Smatt This file is part of GCC.
562a470c0Smatt 
662a470c0Smatt GCC is free software; you can redistribute it and/or modify
762a470c0Smatt it under the terms of the GNU General Public License as published by
862a470c0Smatt the Free Software Foundation; either version 3, or (at your option)
962a470c0Smatt any later version.
1062a470c0Smatt 
1162a470c0Smatt GCC is distributed in the hope that it will be useful,
1262a470c0Smatt but WITHOUT ANY WARRANTY; without even the implied warranty of
1362a470c0Smatt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1462a470c0Smatt GNU General Public License for more details.
1562a470c0Smatt 
1662a470c0Smatt Under Section 7 of GPL version 3, you are granted additional
1762a470c0Smatt permissions described in the GCC Runtime Library Exception, version
1862a470c0Smatt 3.1, as published by the Free Software Foundation.
1962a470c0Smatt 
2062a470c0Smatt You should have received a copy of the GNU General Public License and
2162a470c0Smatt a copy of the GCC Runtime Library Exception along with this program;
2262a470c0Smatt see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2362a470c0Smatt <http://www.gnu.org/licenses/>.  */
2462a470c0Smatt 
2562a470c0Smatt #ifndef inhibit_libc
2681418a27Smrg /* Do code reading to identify a signal frame, and set the frame
2781418a27Smrg    state data appropriately.  See unwind-dw2.c for the structs.  */
2862a470c0Smatt 
2962a470c0Smatt #include <signal.h>
3062a470c0Smatt #include <sys/ucontext.h>
3162a470c0Smatt 
3262a470c0Smatt #define MD_FALLBACK_FRAME_STATE_FOR or1k_fallback_frame_state
3362a470c0Smatt 
3462a470c0Smatt static _Unwind_Reason_Code
or1k_fallback_frame_state(struct _Unwind_Context * context,_Unwind_FrameState * fs)3562a470c0Smatt or1k_fallback_frame_state (struct _Unwind_Context *context,
3662a470c0Smatt 			   _Unwind_FrameState *fs)
3762a470c0Smatt {
3881418a27Smrg   unsigned int *pc = context->ra;
3962a470c0Smatt   struct rt_sigframe {
4062a470c0Smatt     siginfo_t info;
4181418a27Smrg     ucontext_t uc;
4281418a27Smrg   } *rt;
4362a470c0Smatt   struct sigcontext *sc;
4462a470c0Smatt   long new_cfa;
4562a470c0Smatt   int i;
4662a470c0Smatt 
4781418a27Smrg   if (pc[0] != 0xa960008b		/* l.ori r11, r0, NR_rt_sigreturn */
4881418a27Smrg       || pc[1] != 0x20000001)		/* l.sys 1 */
4981418a27Smrg     return _URC_END_OF_STACK;
5081418a27Smrg   if (context->cfa == 0)
5162a470c0Smatt     return _URC_END_OF_STACK;
5262a470c0Smatt 
5381418a27Smrg   rt = context->cfa;
5481418a27Smrg   sc = &rt->uc.uc_mcontext;
5562a470c0Smatt 
5662a470c0Smatt   new_cfa = sc->regs.gpr[1];
5762a470c0Smatt   fs->regs.cfa_how = CFA_REG_OFFSET;
5881418a27Smrg   fs->regs.cfa_reg = 1;
5962a470c0Smatt   fs->regs.cfa_offset = new_cfa - (long) context->cfa;
6081418a27Smrg   for (i = 2; i < 32; ++i)
6162a470c0Smatt     {
6262a470c0Smatt       fs->regs.reg[i].how = REG_SAVED_OFFSET;
6362a470c0Smatt       fs->regs.reg[i].loc.offset = (long) &sc->regs.gpr[i] - new_cfa;
6462a470c0Smatt     }
6581418a27Smrg   fs->regs.reg[32].how = REG_SAVED_OFFSET;
6681418a27Smrg   fs->regs.reg[32].loc.offset = (long)&sc->regs.pc - new_cfa;
6781418a27Smrg   fs->retaddr_column = 32;
6862a470c0Smatt   fs->signal_frame = 1;
6962a470c0Smatt 
7062a470c0Smatt   return _URC_NO_REASON;
7162a470c0Smatt }
7262a470c0Smatt 
7381418a27Smrg #define MD_FROB_UPDATE_CONTEXT or1k_frob_update_context
7481418a27Smrg 
7581418a27Smrg /* Fix up for signal handlers that don't have S flag set.  */
7681418a27Smrg 
7781418a27Smrg static void
or1k_frob_update_context(struct _Unwind_Context * context,_Unwind_FrameState * fs ATTRIBUTE_UNUSED)7881418a27Smrg or1k_frob_update_context (struct _Unwind_Context *context,
7981418a27Smrg 			   _Unwind_FrameState *fs ATTRIBUTE_UNUSED)
8081418a27Smrg {
8181418a27Smrg   unsigned int *pc = context->ra;
8281418a27Smrg 
8381418a27Smrg   if (pc[0] == 0xa960008b		/* l.ori r11, r0, NR_rt_sigreturn */
8481418a27Smrg       && pc[1] == 0x20000001)		/* l.sys 1 */
8581418a27Smrg     _Unwind_SetSignalFrame (context, 1);
8681418a27Smrg }
8781418a27Smrg #endif
88