/* C6X EABI compliant unwinding routines.
   Copyright (C) 2011-2021 Free Software Foundation, Inc.

   This file is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 3, or (at your option) any
   later version.

   This file is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   Under Section 7 of GPL version 3, you are granted additional
   permissions described in the GCC Runtime Library Exception, version
   3.1, as published by the Free Software Foundation.

   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;
   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
   <http://www.gnu.org/licenses/>.  */

#include "unwind.h"

/* Misc constants.  */
#define NUM_SAVED_REGS 32
#define R_B0 16
#define R_B3 (R_B0 + 3)
#define R_B15 (R_B0 + 15)
#define R_SP R_B15
#define R_LR R_B3
#define R_PC 33

#define VRS_PC(vrs) ((vrs)->core.pc)
#define VRS_SP(vrs) ((vrs)->core.reg[R_SP])
#define VRS_RETURN(vrs) ((vrs)->core.reg[R_B3])

struct core_regs
{
  _uw reg[NUM_SAVED_REGS];
  _uw pc;
};

typedef struct
{
  /* The first fields must be the same as a phase2_vrs.  */
  _uw demand_save_flags; /* Currently always zero.  */
  struct core_regs core;
  _uw prev_sp; /* Only valid during forced unwinding.  */
} phase1_vrs;

/* This must match the structure created by the assembly wrappers.  */
typedef struct
{
  _uw demand_save_flags;
  struct core_regs core;
} phase2_vrs;

/* Coprocessor register state manipulation functions.  */

/* Restore coprocessor state after phase1 unwinding.  */
static void
restore_non_core_regs (phase1_vrs * vrs __attribute__((unused)))
{
}

#include "unwind-arm-common.inc"

/* ABI defined personality routines.  */
extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr0 (_Unwind_State,
    _Unwind_Control_Block *, _Unwind_Context *);// __attribute__((weak));
extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr1 (_Unwind_State,
    _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr2 (_Unwind_State,
    _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr3 (_Unwind_State,
    _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr4 (_Unwind_State,
    _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));

/* ABI defined routine to store a virtual register to memory.  */

_Unwind_VRS_Result _Unwind_VRS_Get (_Unwind_Context *context,
				    _Unwind_VRS_RegClass regclass,
				    _uw regno,
				    _Unwind_VRS_DataRepresentation representation,
				    void *valuep)
{
  phase1_vrs *vrs = (phase1_vrs *) context;

  switch (regclass)
    {
    case _UVRSC_CORE:
      if (representation != _UVRSD_UINT32)
	return _UVRSR_FAILED;
      if (regno == R_PC)
	{
	  *(_uw *) valuep = vrs->core.pc;
	  return _UVRSR_OK;
	}
      if (regno >= NUM_SAVED_REGS)
	return _UVRSR_FAILED;
      *(_uw *) valuep = vrs->core.reg[regno];
      return _UVRSR_OK;

    default:
      return _UVRSR_FAILED;
    }
}


/* ABI defined function to load a virtual register from memory.  */

_Unwind_VRS_Result _Unwind_VRS_Set (_Unwind_Context *context,
				    _Unwind_VRS_RegClass regclass,
				    _uw regno,
				    _Unwind_VRS_DataRepresentation representation,
				    void *valuep)
{
  phase1_vrs *vrs = (phase1_vrs *) context;

  switch (regclass)
    {
    case _UVRSC_CORE:
      if (representation != _UVRSD_UINT32)
	return _UVRSR_FAILED;
      if (regno == R_PC)
	{
	  vrs->core.pc = *(_uw *) valuep;
	  return _UVRSR_OK;
	}
      if (regno >= NUM_SAVED_REGS)
	return _UVRSR_FAILED;

      vrs->core.reg[regno] = *(_uw *) valuep;
      return _UVRSR_OK;

    default:
      return _UVRSR_FAILED;
    }
}


/* Core unwinding functions.  */

/* Calculate the address encoded by a 31-bit self-relative offset at address
   P.  */
static inline _uw
selfrel_offset31 (const _uw *p)
{
  _uw offset;

  offset = *p << 1;
  return offset + (_uw) p;
}


static _uw
__gnu_unwind_get_pr_addr (int idx)
{
  switch (idx)
    {
    case 0:
      return (_uw) &__c6xabi_unwind_cpp_pr0;

    case 1:
      return (_uw) &__c6xabi_unwind_cpp_pr1;

    case 2:
      return (_uw) &__c6xabi_unwind_cpp_pr2;

    case 3:
      return (_uw) &__c6xabi_unwind_cpp_pr3;

    case 4:
      return (_uw) &__c6xabi_unwind_cpp_pr4;

    default:
       return 0;
    }
}


/* ABI defined personality routine entry points.  */

_Unwind_Reason_Code
__c6xabi_unwind_cpp_pr0 (_Unwind_State state,
			_Unwind_Control_Block *ucbp,
			_Unwind_Context *context)
{
  return __gnu_unwind_pr_common (state, ucbp, context, 0);
}

_Unwind_Reason_Code
__c6xabi_unwind_cpp_pr1 (_Unwind_State state,
			_Unwind_Control_Block *ucbp,
			_Unwind_Context *context)
{
  return __gnu_unwind_pr_common (state, ucbp, context, 1);
}

_Unwind_Reason_Code
__c6xabi_unwind_cpp_pr2 (_Unwind_State state,
			_Unwind_Control_Block *ucbp,
			_Unwind_Context *context)
{
  return __gnu_unwind_pr_common (state, ucbp, context, 2);
}

_Unwind_Reason_Code
__c6xabi_unwind_cpp_pr3 (_Unwind_State state,
			_Unwind_Control_Block *ucbp,
			_Unwind_Context *context)
{
  return __gnu_unwind_pr_common (state, ucbp, context, 3);
}

_Unwind_Reason_Code
__c6xabi_unwind_cpp_pr4 (_Unwind_State state,
			_Unwind_Control_Block *ucbp,
			_Unwind_Context *context)
{
  return __gnu_unwind_pr_common (state, ucbp, context, 4);
}
