gdb/gdbserver/linux-xtensa-low.c - gdb

Global variables defined

Data types defined

Functions defined

Macros defined

Source code

  1. /* GNU/Linux/Xtensa specific low level interface, for the remote server for GDB.
  2.    Copyright (C) 2007-2015 Free Software Foundation, Inc.

  3.    This file is part of GDB.

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

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

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


  14. #include "server.h"
  15. #include "linux-low.h"

  16. /* Defined in auto-generated file reg-xtensa.c.  */
  17. void init_registers_xtensa (void);
  18. extern const struct target_desc *tdesc_xtensa;

  19. #include <asm/ptrace.h>
  20. #include <xtensa-config.h>

  21. #include "xtensa-xtregs.c"

  22. enum regnum {
  23.         R_PC=0,        R_PS,
  24.         R_LBEG,        R_LEND,        R_LCOUNT,
  25.         R_SAR,
  26.         R_WS, R_WB,
  27.         R_A0 = 64
  28. };

  29. static void
  30. xtensa_fill_gregset (struct regcache *regcache, void *buf)
  31. {
  32.   elf_greg_t* rset = (elf_greg_t*)buf;
  33.   const struct target_desc *tdesc = regcache->tdesc;
  34.   int ar0_regnum;
  35.   char *ptr;
  36.   int i;

  37.   /* Take care of AR registers.  */

  38.   ar0_regnum = find_regno (tdesc, "ar0");
  39.   ptr = (char*)&rset[R_A0];

  40.   for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++)
  41.     {
  42.       collect_register (regcache, i, ptr);
  43.       ptr += register_size (tdesc, i);
  44.     }

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

  46. #if XCHAL_HAVE_LOOP
  47.   collect_register_by_name (regcache, "lbeg", (char*)&rset[R_LBEG]);
  48.   collect_register_by_name (regcache, "lend", (char*)&rset[R_LEND]);
  49.   collect_register_by_name (regcache, "lcount", (char*)&rset[R_LCOUNT]);
  50. #endif

  51.   collect_register_by_name (regcache, "sar", (char*)&rset[R_SAR]);
  52.   collect_register_by_name (regcache, "pc", (char*)&rset[R_PC]);
  53.   collect_register_by_name (regcache, "ps", (char*)&rset[R_PS]);
  54.   collect_register_by_name (regcache, "windowbase", (char*)&rset[R_WB]);
  55.   collect_register_by_name (regcache, "windowstart", (char*)&rset[R_WS]);
  56. }

  57. static void
  58. xtensa_store_gregset (struct regcache *regcache, const void *buf)
  59. {
  60.   const elf_greg_t* rset = (const elf_greg_t*)buf;
  61.   const struct target_desc *tdesc = regcache->tdesc;
  62.   int ar0_regnum;
  63.   char *ptr;
  64.   int i;

  65.   /* Take care of AR registers.  */

  66.   ar0_regnum = find_regno (tdesc, "ar0");
  67.   ptr = (char *)&rset[R_A0];

  68.   for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++)
  69.     {
  70.       supply_register (regcache, i, ptr);
  71.       ptr += register_size (tdesc, i);
  72.     }

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

  74. #if XCHAL_HAVE_LOOP
  75.   supply_register_by_name (regcache, "lbeg", (char*)&rset[R_LBEG]);
  76.   supply_register_by_name (regcache, "lend", (char*)&rset[R_LEND]);
  77.   supply_register_by_name (regcache, "lcount", (char*)&rset[R_LCOUNT]);
  78. #endif

  79.   supply_register_by_name (regcache, "sar", (char*)&rset[R_SAR]);
  80.   supply_register_by_name (regcache, "pc", (char*)&rset[R_PC]);
  81.   supply_register_by_name (regcache, "ps", (char*)&rset[R_PS]);
  82.   supply_register_by_name (regcache, "windowbase", (char*)&rset[R_WB]);
  83.   supply_register_by_name (regcache, "windowstart", (char*)&rset[R_WS]);
  84. }

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

  86. static void
  87. xtensa_fill_xtregset (struct regcache *regcache, void *buf)
  88. {
  89.   const xtensa_regtable_t *ptr;

  90.   for (ptr = xtensa_regmap_table; ptr->name; ptr++)
  91.     {
  92.       collect_register_by_name (regcache, ptr->name,
  93.                                 (char*)buf + ptr->ptrace_offset);
  94.     }
  95. }

  96. static void
  97. xtensa_store_xtregset (struct regcache *regcache, const void *buf)
  98. {
  99.   const xtensa_regtable_t *ptr;

  100.   for (ptr = xtensa_regmap_table; ptr->name; ptr++)
  101.     {
  102.       supply_register_by_name (regcache, ptr->name,
  103.                                 (char*)buf + ptr->ptrace_offset);
  104.     }
  105. }

  106. static struct regset_info xtensa_regsets[] = {
  107.   { PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
  108.     GENERAL_REGS,
  109.     xtensa_fill_gregset, xtensa_store_gregset },
  110.   { PTRACE_GETXTREGS, PTRACE_SETXTREGS, 0, XTENSA_ELF_XTREG_SIZE,
  111.     EXTENDED_REGS,
  112.     xtensa_fill_xtregset, xtensa_store_xtregset },
  113.   { 0, 0, 0, -1, -1, NULL, NULL }
  114. };

  115. #if XCHAL_HAVE_BE
  116. #define XTENSA_BREAKPOINT {0xd2,0x0f}
  117. #else
  118. #define XTENSA_BREAKPOINT {0x2d,0xf0}
  119. #endif

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

  122. static CORE_ADDR
  123. xtensa_get_pc (struct regcache *regcache)
  124. {
  125.   unsigned long pc;

  126.   collect_register_by_name (regcache, "pc", &pc);
  127.   return pc;
  128. }

  129. static void
  130. xtensa_set_pc (struct regcache *regcache, CORE_ADDR pc)
  131. {
  132.   unsigned long newpc = pc;
  133.   supply_register_by_name (regcache, "pc", &newpc);
  134. }

  135. static int
  136. xtensa_breakpoint_at (CORE_ADDR where)
  137. {
  138.     unsigned long insn;

  139.     (*the_target->read_memory) (where, (unsigned char *) &insn,
  140.                                 xtensa_breakpoint_len);
  141.     return memcmp((char *) &insn,
  142.                   xtensa_breakpoint, xtensa_breakpoint_len) == 0;
  143. }

  144. static struct regsets_info xtensa_regsets_info =
  145.   {
  146.     xtensa_regsets, /* regsets */
  147.     0, /* num_regsets */
  148.     NULL, /* disabled_regsets */
  149.   };

  150. static struct usrregs_info xtensa_usrregs_info =
  151.   {
  152.     xtensa_num_regs,
  153.     xtensa_regmap,
  154.   };

  155. static struct regs_info regs_info =
  156.   {
  157.     NULL, /* regset_bitmap */
  158.     &xtensa_usrregs_info,
  159.     &xtensa_regsets_info
  160.   };

  161. static void
  162. xtensa_arch_setup (void)
  163. {
  164.   current_process ()->tdesc = tdesc_xtensa;
  165. }

  166. static const struct regs_info *
  167. xtensa_regs_info (void)
  168. {
  169.   return &regs_info;
  170. }

  171. struct linux_target_ops the_low_target = {
  172.   xtensa_arch_setup,
  173.   xtensa_regs_info,
  174.   0,
  175.   0,
  176.   NULL, /* fetch_register */
  177.   xtensa_get_pc,
  178.   xtensa_set_pc,
  179.   xtensa_breakpoint,
  180.   xtensa_breakpoint_len,
  181.   NULL,
  182.   0,
  183.   xtensa_breakpoint_at,
  184. };


  185. void
  186. initialize_low_arch (void)
  187. {
  188.   /* Initialize the Linux target descriptions.  */
  189.   init_registers_xtensa ();

  190.   initialize_regsets_info (&xtensa_regsets_info);
  191. }