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

Global variables defined

Data types defined

Functions defined

Macros defined

Source code

  1. /* Target dependent code for GDB on TI C6x systems.

  2.    Copyright (C) 2010-2015 Free Software Foundation, Inc.
  3.    Contributed by Andrew Jenner <andrew@codesourcery.com>
  4.    Contributed by Yao Qi <yao@codesourcery.com>

  5.    This file is part of GDB.

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

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

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

  16. #include "server.h"
  17. #include "linux-low.h"

  18. #include <sys/ptrace.h>
  19. #include <endian.h>

  20. #include "gdb_proc_service.h"

  21. #ifndef PTRACE_GET_THREAD_AREA
  22. #define PTRACE_GET_THREAD_AREA 25
  23. #endif

  24. /* There are at most 69 registers accessible in ptrace.  */
  25. #define TIC6X_NUM_REGS 69

  26. #include <asm/ptrace.h>

  27. /* Defined in auto-generated file tic6x-c64xp-linux.c.  */
  28. void init_registers_tic6x_c64xp_linux (void);
  29. extern const struct target_desc *tdesc_tic6x_c64xp_linux;

  30. /* Defined in auto-generated file tic6x-c64x-linux.c.  */
  31. void init_registers_tic6x_c64x_linux (void);
  32. extern const struct target_desc *tdesc_tic6x_c64x_linux;

  33. /* Defined in auto-generated file tic62x-c6xp-linux.c.  */
  34. void init_registers_tic6x_c62x_linux (void);
  35. extern const struct target_desc *tdesc_tic6x_c62x_linux;

  36. union tic6x_register
  37. {
  38.   unsigned char buf[4];

  39.   int reg32;
  40. };

  41. /* Return the ptrace ``address'' of register REGNO.  */

  42. #if __BYTE_ORDER == __BIG_ENDIAN
  43. static int tic6x_regmap_c64xp[] = {
  44.   /* A0 - A15 */
  45.   53, 52, 55, 54, 57, 56, 59, 58,
  46.   61, 60, 63, 62, 65, 64, 67, 66,
  47.   /* B0 - B15 */
  48.   23, 22, 25, 24, 27, 26, 29, 28,
  49.   31, 30, 33, 32, 35, 34, 69, 68,
  50.   /* CSR PC */
  51.   5, 4,
  52.   /* A16 - A31 */
  53.   37, 36, 39, 38, 41, 40, 43, 42,
  54.   45, 44, 47, 46, 49, 48, 51, 50,
  55.   /* B16 - B31 */
  56.   769811, 10, 13, 12,
  57.   15, 14, 17, 16, 19, 18, 21, 20,
  58.   /* TSR, ILC, RILC */
  59.   12, 3
  60. };

  61. static int tic6x_regmap_c64x[] = {
  62.   /* A0 - A15 */
  63.   51, 50, 53, 52, 55, 54, 57, 56,
  64.   59, 58, 61, 60, 63, 62, 65, 64,
  65.   /* B0 - B15 */
  66.   21, 20, 23, 22, 25, 24, 27, 26,
  67.   29, 28, 31, 30, 33, 32, 67, 66,
  68.   /* CSR PC */
  69.   32,
  70.   /* A16 - A31 */
  71.   35, 34, 37, 36, 39, 38, 41, 40,
  72.   43, 42, 45, 44, 47, 46, 49, 48,
  73.   /* B16 - B31 */
  74.   54769811, 10,
  75.   13, 12, 15, 14, 17, 16, 19, 18,
  76.   -1, -1, -1
  77. };

  78. static int tic6x_regmap_c62x[] = {
  79.   /* A0 - A15 */
  80.   19, 18, 21, 20, 23, 22, 25, 24,
  81.   27, 26, 29, 28, 31, 30, 33, 32,
  82.   /* B0 - B15 */
  83.    547698, 11, 10,
  84.   13, 12, 15, 14, 17, 16, 35, 34,
  85.   /* CSR, PC */
  86.   3, 2,
  87.   -1, -1, -1, -1, -1, -1, -1, -1,
  88.   -1, -1, -1, -1, -1, -1, -1, -1,
  89.   -1, -1, -1, -1, -1, -1, -1, -1,
  90.   -1, -1, -1, -1, -1, -1, -1, -1,
  91.   -1, -1, -1
  92. };

  93. #else
  94. static int tic6x_regmap_c64xp[] = {
  95.   /* A0 - A15 */
  96.   52, 53, 54, 55, 56, 57, 58, 59,
  97.   60, 61, 62, 63, 64, 65, 66, 67,
  98.   /* B0 - B15 */
  99.   22, 23, 24, 25, 26, 27, 28, 29,
  100.   30, 31, 32, 33, 34, 35, 68, 69,
  101.   /* CSR PC */
  102.    45,
  103.   /* A16 - A31 */
  104.   36, 37, 38, 39, 40, 41, 42, 43,
  105.   44, 45, 46, 47, 48, 49, 50, 51,
  106.   /* B16 -B31 */
  107.    6789, 10, 11, 12, 13,
  108.   14, 15, 16, 17, 18, 19, 20, 31,
  109.   /* TSR, ILC, RILC */
  110.   03, 2
  111. };

  112. static int tic6x_regmap_c64x[] = {
  113.   /* A0 - A15 */
  114.   50, 51, 52, 53, 54, 55, 56, 57,
  115.   58, 59, 60, 61, 62, 63, 64, 65,
  116.   /* B0 - B15 */
  117.   20, 21, 22, 23, 24, 25, 26, 27,
  118.   28, 29, 30, 31, 32, 33, 66, 67,
  119.   /* CSR PC */
  120.   23,
  121.   /* A16 - A31 */
  122.   34, 35, 36, 37, 38, 39, 40, 41,
  123.   42, 43, 44, 45, 46, 47, 48, 49,
  124.   /* B16 - B31 */
  125.   45678910, 11,
  126.   12, 13, 14, 15, 16, 17, 18, 19,
  127.   -1, -1, -1
  128. };

  129. static int tic6x_regmap_c62x[] = {
  130.   /* A0 - A15 */
  131.   18, 19, 20, 21, 22, 23, 24, 25,
  132.   26, 27, 28, 29, 30, 31, 32, 33,
  133.   /* B0 - B15 */
  134.   456789, 10, 11,
  135.   12, 13, 14, 15, 16, 17, 34, 35,
  136.   /* CSR PC */
  137.   23,
  138.   -1, -1, -1, -1, -1, -1, -1, -1,
  139.   -1, -1, -1, -1, -1, -1, -1, -1,
  140.   -1, -1, -1, -1, -1, -1, -1, -1,
  141.   -1, -1, -1, -1, -1, -1, -1, -1,
  142.   -1, -1, -1
  143. };

  144. #endif

  145. extern struct linux_target_ops the_low_target;

  146. static int *tic6x_regmap;
  147. static unsigned int tic6x_breakpoint;

  148. /* Forward definition.  */
  149. static struct usrregs_info tic6x_usrregs_info;

  150. static const struct target_desc *
  151. tic6x_read_description (void)
  152. {
  153.   register unsigned int csr asm ("B2");
  154.   unsigned int cpuid;
  155.   const struct target_desc *tdesc;

  156.   /* Determine the CPU we're running on to find the register order.  */
  157.   __asm__ ("MVC .S2 CSR,%0" : "=r" (csr) :);
  158.   cpuid = csr >> 24;
  159.   switch (cpuid)
  160.     {
  161.     case 0x00: /* C62x */
  162.     case 0x02: /* C67x */
  163.       tic6x_regmap = tic6x_regmap_c62x;
  164.       tic6x_breakpoint = 0x0000a122/* BNOP .S2 0,5 */
  165.       tdesc = tdesc_tic6x_c62x_linux;
  166.       break;
  167.     case 0x03: /* C67x+ */
  168.       tic6x_regmap = tic6x_regmap_c64x;
  169.       tic6x_breakpoint = 0x0000a122/* BNOP .S2 0,5 */
  170.       tdesc = tdesc_tic6x_c64x_linux;
  171.       break;
  172.     case 0x0c: /* C64x */
  173.       tic6x_regmap = tic6x_regmap_c64x;
  174.       tic6x_breakpoint = 0x0000a122/* BNOP .S2 0,5 */
  175.       tdesc = tdesc_tic6x_c64x_linux;
  176.       break;
  177.     case 0x10: /* C64x+ */
  178.     case 0x14: /* C674x */
  179.     case 0x15: /* C66x */
  180.       tic6x_regmap = tic6x_regmap_c64xp;
  181.       tic6x_breakpoint = 0x56454314/* illegal opcode */
  182.       tdesc = tdesc_tic6x_c64xp_linux;
  183.       break;
  184.     default:
  185.       error ("Unknown CPU ID 0x%02x", cpuid);
  186.     }
  187.   tic6x_usrregs_info.regmap = tic6x_regmap;
  188.   return tdesc;
  189. }

  190. static int
  191. tic6x_cannot_fetch_register (int regno)
  192. {
  193.   return (tic6x_regmap[regno] == -1);
  194. }

  195. static int
  196. tic6x_cannot_store_register (int regno)
  197. {
  198.   return (tic6x_regmap[regno] == -1);
  199. }

  200. static CORE_ADDR
  201. tic6x_get_pc (struct regcache *regcache)
  202. {
  203.   union tic6x_register pc;

  204.   collect_register_by_name (regcache, "PC", pc.buf);
  205.   return pc.reg32;
  206. }

  207. static void
  208. tic6x_set_pc (struct regcache *regcache, CORE_ADDR pc)
  209. {
  210.   union tic6x_register newpc;

  211.   newpc.reg32 = pc;
  212.   supply_register_by_name (regcache, "PC", newpc.buf);
  213. }

  214. #define tic6x_breakpoint_len 4

  215. static int
  216. tic6x_breakpoint_at (CORE_ADDR where)
  217. {
  218.   unsigned int insn;

  219.   (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
  220.   if (insn == tic6x_breakpoint)
  221.     return 1;

  222.   /* If necessary, recognize more trap instructions here.  GDB only uses the
  223.      one.  */
  224.   return 0;
  225. }

  226. /* Fetch the thread-local storage pointer for libthread_db.  */

  227. ps_err_e
  228. ps_get_thread_area (const struct ps_prochandle *ph,
  229.                     lwpid_t lwpid, int idx, void **base)
  230. {
  231.   if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
  232.     return PS_ERR;

  233.   /* IDX is the bias from the thread pointer to the beginning of the
  234.      thread descriptor.  It has to be subtracted due to implementation
  235.      quirks in libthread_db.  */
  236.   *base = (void *) ((char *) *base - idx);

  237.   return PS_OK;
  238. }

  239. static void
  240. tic6x_collect_register (struct regcache *regcache, int regno,
  241.                         union tic6x_register *reg)
  242. {
  243.   union tic6x_register tmp_reg;

  244.   collect_register (regcache, regno, &tmp_reg.reg32);
  245.   reg->reg32 = tmp_reg.reg32;
  246. }

  247. static void
  248. tic6x_supply_register (struct regcache *regcache, int regno,
  249.                        const union tic6x_register *reg)
  250. {
  251.   int offset = 0;

  252.   supply_register (regcache, regno, reg->buf + offset);
  253. }

  254. static void
  255. tic6x_fill_gregset (struct regcache *regcache, void *buf)
  256. {
  257.   union tic6x_register *regset = buf;
  258.   int i;

  259.   for (i = 0; i < TIC6X_NUM_REGS; i++)
  260.     if (tic6x_regmap[i] != -1)
  261.       tic6x_collect_register (regcache, i, regset + tic6x_regmap[i]);
  262. }

  263. static void
  264. tic6x_store_gregset (struct regcache *regcache, const void *buf)
  265. {
  266.   const union tic6x_register *regset = buf;
  267.   int i;

  268.   for (i = 0; i < TIC6X_NUM_REGS; i++)
  269.     if (tic6x_regmap[i] != -1)
  270.       tic6x_supply_register (regcache, i, regset + tic6x_regmap[i]);
  271. }

  272. static struct regset_info tic6x_regsets[] = {
  273.   { PTRACE_GETREGS, PTRACE_SETREGS, 0, TIC6X_NUM_REGS * 4, GENERAL_REGS,
  274.     tic6x_fill_gregset, tic6x_store_gregset },
  275.   { 0, 0, 0, -1, -1, NULL, NULL }
  276. };

  277. static void
  278. tic6x_arch_setup (void)
  279. {
  280.   current_process ()->tdesc = tic6x_read_description ();
  281. }

  282. static struct regsets_info tic6x_regsets_info =
  283.   {
  284.     tic6x_regsets, /* regsets */
  285.     0, /* num_regsets */
  286.     NULL, /* disabled_regsets */
  287.   };

  288. static struct usrregs_info tic6x_usrregs_info =
  289.   {
  290.     TIC6X_NUM_REGS,
  291.     NULL, /* Set in tic6x_read_description.  */
  292.   };

  293. static struct regs_info regs_info =
  294.   {
  295.     NULL, /* regset_bitmap */
  296.     &tic6x_usrregs_info,
  297.     &tic6x_regsets_info
  298.   };

  299. static const struct regs_info *
  300. tic6x_regs_info (void)
  301. {
  302.   return &regs_info;
  303. }

  304. struct linux_target_ops the_low_target = {
  305.   tic6x_arch_setup,
  306.   tic6x_regs_info,
  307.   tic6x_cannot_fetch_register,
  308.   tic6x_cannot_store_register,
  309.   NULL, /* fetch_register */
  310.   tic6x_get_pc,
  311.   tic6x_set_pc,
  312.   (const unsigned char *) &tic6x_breakpoint,
  313.   tic6x_breakpoint_len,
  314.   NULL,
  315.   0,
  316.   tic6x_breakpoint_at,
  317. };

  318. void
  319. initialize_low_arch (void)
  320. {
  321.   /* Initialize the Linux target descriptions.  */
  322.   init_registers_tic6x_c64xp_linux ();
  323.   init_registers_tic6x_c64x_linux ();
  324.   init_registers_tic6x_c62x_linux ();

  325.   initialize_regsets_info (&tic6x_regsets_info);
  326. }