/* GNU/Linux/Xtensa specific low level interface, for the remote server for GDB.
   Copyright 2007, 2008 Free Software Foundation, Inc.

   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 "server.h"
#include "linux-low.h"

/* Defined in auto-generated file reg-xtensa.c.  */
void init_registers_xtensa (void);

#include <sys/ptrace.h>
#include <xtensa-config.h>

#include "xtensa-xtregs.c"

enum regnum {
	R_PC=0,	R_PS,
	R_LBEG,	R_LEND,	R_LCOUNT,
	R_SAR,
	R_WS, R_WB,
	R_A0 = 64 
};

static void
xtensa_fill_gregset (void *buf)
{
  elf_greg_t* rset = (elf_greg_t*)buf;
  int ar0_regnum;
  char *ptr;
  int i;

  /* Take care of AR registers.  */

  ar0_regnum = find_regno ("ar0");
  ptr = (char*)&rset[R_A0];

  for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++)
    {
      collect_register (i, ptr);
      ptr += register_size(i);
    }

  /* Loop registers, if hardware has it.  */

#if XCHAL_HAVE_LOOP
  collect_register_by_name ("lbeg", (char*)&rset[R_LBEG]);
  collect_register_by_name ("lend", (char*)&rset[R_LEND]);
  collect_register_by_name ("lcount", (char*)&rset[R_LCOUNT]);
#endif

  collect_register_by_name ("sar", (char*)&rset[R_SAR]);
  collect_register_by_name ("pc", (char*)&rset[R_PC]);
  collect_register_by_name ("ps", (char*)&rset[R_PS]);
  collect_register_by_name ("windowbase", (char*)&rset[R_WB]);
  collect_register_by_name ("windowstart", (char*)&rset[R_WS]);
}

static void
xtensa_store_gregset (const void *buf)
{
  const elf_greg_t* rset = (const elf_greg_t*)buf;
  int ar0_regnum;
  char *ptr;
  int i;

  /* Take care of AR registers.  */

  ar0_regnum = find_regno ("ar0");
  ptr = (char *)&rset[R_A0];

  for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++)
    {
      supply_register (i, ptr);
      ptr += register_size(i);
    }

  /* Loop registers, if hardware has it.  */

#if XCHAL_HAVE_LOOP
  supply_register_by_name ("lbeg", (char*)&rset[R_LBEG]);
  supply_register_by_name ("lend", (char*)&rset[R_LEND]);
  supply_register_by_name ("lcount", (char*)&rset[R_LCOUNT]);
#endif

  supply_register_by_name ("sar", (char*)&rset[R_SAR]);
  supply_register_by_name ("pc", (char*)&rset[R_PC]);
  supply_register_by_name ("ps", (char*)&rset[R_PS]);
  supply_register_by_name ("windowbase", (char*)&rset[R_WB]);
  supply_register_by_name ("windowstart", (char*)&rset[R_WS]);
}

/* Xtensa GNU/Linux PTRACE interface includes extended register set.  */

static void
xtensa_fill_xtregset (void *buf)
{
  const xtensa_regtable_t *ptr;

  for (ptr = xtensa_regmap_table; ptr->name; ptr++)
    {
      collect_register_by_name (ptr->name,
				(char*)buf + ptr->ptrace_offset);
    }
}

static void
xtensa_store_xtregset (const void *buf)
{
  const xtensa_regtable_t *ptr;

  for (ptr = xtensa_regmap_table; ptr->name; ptr++)
    {
      supply_register_by_name (ptr->name,
				(char*)buf + ptr->ptrace_offset);
    }
}

struct regset_info target_regsets[] = {
  { PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
    GENERAL_REGS,
    xtensa_fill_gregset, xtensa_store_gregset },
  { PTRACE_GETXTREGS, PTRACE_SETXTREGS, XTENSA_ELF_XTREG_SIZE,
    EXTENDED_REGS,
    xtensa_fill_xtregset, xtensa_store_xtregset },
  { 0, 0, -1, -1, NULL, NULL }
};

#if XCHAL_HAVE_BE
#define XTENSA_BREAKPOINT {0xd2,0x0f}
#else
#define XTENSA_BREAKPOINT {0x2d,0xf0}
#endif

static const unsigned char xtensa_breakpoint[] = XTENSA_BREAKPOINT;
#define xtensa_breakpoint_len 2

static CORE_ADDR
xtensa_get_pc (void)
{
  unsigned long pc;

  collect_register_by_name ("pc", &pc);
  return pc;
}

static void
xtensa_set_pc (CORE_ADDR pc)
{
  unsigned long newpc = pc;
  supply_register_by_name ("pc", &newpc);
}

static int
xtensa_breakpoint_at (CORE_ADDR where)
{
    unsigned long insn;

    (*the_target->read_memory) (where, (unsigned char *) &insn,
				xtensa_breakpoint_len);
    return memcmp((char *)&insn, xtensa_breakpoint, xtensa_breakpoint_len) == 0;
}

struct linux_target_ops the_low_target = {
  init_registers_xtensa,
  0,
  0,
  0,
  0,
  xtensa_get_pc,
  xtensa_set_pc,
  xtensa_breakpoint,
  xtensa_breakpoint_len,
  NULL,
  0,
  xtensa_breakpoint_at,
};
