/* GNU/Linux on  TI C6x target support.
   Copyright (C) 2011-2016 Free Software Foundation, Inc.
   Contributed by Yao Qi <yao@codesourcery.com>

   This file is part of GDB.

   This program 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 of the License, or
   (at your option) any later version.

   This program 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.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "defs.h"
#include "solib.h"
#include "osabi.h"
#include "linux-tdep.h"
#include "tic6x-tdep.h"
#include "trad-frame.h"
#include "tramp-frame.h"
#include "elf-bfd.h"
#include "elf/tic6x.h"

#include "features/tic6x-c64xp-linux.c"
#include "features/tic6x-c64x-linux.c"
#include "features/tic6x-c62x-linux.c"

/* The offset from rt_sigframe pointer to SP register.  */
#define TIC6X_SP_RT_SIGFRAME 8
/* Size of struct siginfo info.  */
#define TIC6X_SIGINFO_SIZE 128
/* Size of type stack_t, which contains three fields of type void*, int, and
   size_t respectively.  */
#define TIC6X_STACK_T_SIZE (3 * 4)

static const gdb_byte tic6x_bkpt_bnop_be[] = { 0x00, 0x00, 0xa1, 0x22 };
static const gdb_byte tic6x_bkpt_bnop_le[] = { 0x22, 0xa1, 0x00, 0x00 };

/* Return the offset of register REGNUM in struct sigcontext.  Return 0 if no
   such register in sigcontext.  */

static unsigned int
tic6x_register_sigcontext_offset (unsigned int regnum, struct gdbarch *gdbarch)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  if (regnum == TIC6X_A4_REGNUM || regnum == TIC6X_A4_REGNUM + 2
      || regnum == TIC6X_A4_REGNUM + 4)
    return 4 * (regnum - TIC6X_A4_REGNUM + 2);	/* A4, A6, A8 */
  else if (regnum == TIC6X_A5_REGNUM || regnum == TIC6X_A5_REGNUM + 2
	   || regnum == TIC6X_A5_REGNUM + 4)
    return 4 * (regnum - TIC6X_A5_REGNUM + 12);	/* A5, A7, A9 */
  else if (regnum == TIC6X_B4_REGNUM || regnum == TIC6X_B4_REGNUM + 2
	   || regnum == TIC6X_B4_REGNUM + 4)
    return 4 * (regnum - TIC6X_B4_REGNUM + 3);	/* B4, B6, B8 */
  else if (regnum == TIC6X_B5_REGNUM || regnum == TIC6X_B5_REGNUM + 2
	   || regnum == TIC6X_B5_REGNUM + 4)
    return 4 * (regnum - TIC6X_B5_REGNUM + 19);	/* B5, B7, B9 */
  else if (regnum < TIC6X_A4_REGNUM)
    return 4 * (regnum - 0 + 8);	/* A0 - A3 */
  else if (regnum >= TIC6X_B0_REGNUM && regnum < TIC6X_B4_REGNUM)
    return 4 * (regnum - TIC6X_B0_REGNUM + 15);	/* B0 - B3 */
  else if (regnum >= 34 && regnum < 34 + 32)
    return 4 * (regnum - 34 + 23);	/* A16 - A31, B16 - B31 */
  else if (regnum == TIC6X_PC_REGNUM)
    return 4 * (tdep->has_gp ? 55 : 23);
  else if (regnum == TIC6X_SP_REGNUM)
    return 4;

  return 0;
}

/* Support unwinding frame in signal trampoline.  We don't check sigreturn,
   since it is not used in kernel.  */

static void
tic6x_linux_rt_sigreturn_init (const struct tramp_frame *self,
			       struct frame_info *this_frame,
			       struct trad_frame_cache *this_cache,
			       CORE_ADDR func)
{
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  CORE_ADDR sp = get_frame_register_unsigned (this_frame, TIC6X_SP_REGNUM);
  /* The base of struct sigcontext is computed by examining the definition of
     struct rt_sigframe in linux kernel source arch/c6x/kernel/signal.c.  */
  CORE_ADDR base = (sp + TIC6X_SP_RT_SIGFRAME
		    /* Pointer type *pinfo and *puc in struct rt_sigframe.  */
		    + 4 + 4
		    + TIC6X_SIGINFO_SIZE
		    + 4 + 4 /* uc_flags and *uc_link in struct ucontext.  */
		    + TIC6X_STACK_T_SIZE);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  unsigned int reg_offset;
  unsigned int i;

  for (i = 0; i < 10; i++)	/* A0 - A9 */
    {
      reg_offset = tic6x_register_sigcontext_offset (i, gdbarch);
      gdb_assert (reg_offset != 0);

      trad_frame_set_reg_addr (this_cache, i, base + reg_offset);
    }

  for (i = TIC6X_B0_REGNUM; i < TIC6X_B0_REGNUM + 10; i++)	/* B0 - B9 */
    {
      reg_offset = tic6x_register_sigcontext_offset (i, gdbarch);
      gdb_assert (reg_offset != 0);

      trad_frame_set_reg_addr (this_cache, i, base + reg_offset);
    }

  if (tdep->has_gp)
    for (i = 34; i < 34 + 32; i++)	/* A16 - A31, B16 - B31 */
      {
	reg_offset = tic6x_register_sigcontext_offset (i, gdbarch);
	gdb_assert (reg_offset != 0);

	trad_frame_set_reg_addr (this_cache, i, base + reg_offset);
      }

  trad_frame_set_reg_addr (this_cache, TIC6X_PC_REGNUM,
			   base + tic6x_register_sigcontext_offset (TIC6X_PC_REGNUM,
								    gdbarch));
  trad_frame_set_reg_addr (this_cache, TIC6X_SP_REGNUM,
			   base + tic6x_register_sigcontext_offset (TIC6X_SP_REGNUM,
								    gdbarch));

  /* Save a frame ID.  */
  trad_frame_set_id (this_cache, frame_id_build (sp, func));
}

static struct tramp_frame tic6x_linux_rt_sigreturn_tramp_frame =
{
  SIGTRAMP_FRAME,
  4,
  {
    {0x000045aa, 0x0fffffff},	/* mvk .S2 139,b0 */
    {0x10000000, -1},		/* swe */
    {TRAMP_SENTINEL_INSN}
  },
  tic6x_linux_rt_sigreturn_init
};

/* When FRAME is at a syscall instruction, return the PC of the next
   instruction to be executed.  */

static CORE_ADDR
tic6x_linux_syscall_next_pc (struct frame_info *frame)
{
  ULONGEST syscall_number = get_frame_register_unsigned (frame,
							 TIC6X_B0_REGNUM);
  CORE_ADDR pc = get_frame_pc (frame);

  if (syscall_number == 139 /* rt_sigreturn */)
    return frame_unwind_caller_pc (frame);

  return pc + 4;
}


extern struct target_so_ops dsbt_so_ops;
static void
tic6x_uclinux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  linux_init_abi (info, gdbarch);

  /* Shared library handling.  */
  set_solib_ops (gdbarch, &dsbt_so_ops);

  tdep->syscall_next_pc = tic6x_linux_syscall_next_pc;

#ifdef HAVE_ELF
  /* In tic6x Linux kernel, breakpoint instructions varies on different archs.
     On C64x+ and C67x+, breakpoint instruction is 0x56454314, which is an
     illegal opcode.  On other arch, breakpoint instruction is 0x0000a122
     (BNOP .S2 0,5).  */
  if (info.abfd)
    switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_PROC, Tag_ISA))
      {
      case C6XABI_Tag_ISA_C64XP:
      case C6XABI_Tag_ISA_C67XP:
	if (info.byte_order == BFD_ENDIAN_BIG)
	  tdep->breakpoint = tic6x_bkpt_illegal_opcode_be;
	else
	  tdep->breakpoint = tic6x_bkpt_illegal_opcode_le;
	break;
      default:
	{
	  if (info.byte_order == BFD_ENDIAN_BIG)
	    tdep->breakpoint = tic6x_bkpt_bnop_be;
	  else
	    tdep->breakpoint = tic6x_bkpt_bnop_le;
	}
      }
#endif

  /* Signal trampoline support.  */
  tramp_frame_prepend_unwinder (gdbarch,
				&tic6x_linux_rt_sigreturn_tramp_frame);
}

/* Provide a prototype to silence -Wmissing-prototypes.  */
extern initialize_file_ftype _initialize_tic6x_linux_tdep;

void
_initialize_tic6x_linux_tdep (void)
{
  gdbarch_register_osabi (bfd_arch_tic6x, 0, GDB_OSABI_LINUX,
			  tic6x_uclinux_init_abi);

  initialize_tdesc_tic6x_c64xp_linux ();
  initialize_tdesc_tic6x_c64x_linux ();
  initialize_tdesc_tic6x_c62x_linux ();
}
