gdb/sparc-ravenscar-thread.c - gdb

Global variables defined

Functions defined

Source code

  1. /* Ravenscar SPARC target support.

  2.    Copyright (C) 2004-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 "defs.h"
  15. #include "gdbcore.h"
  16. #include "regcache.h"
  17. #include "sparc-tdep.h"
  18. #include "inferior.h"
  19. #include "ravenscar-thread.h"
  20. #include "sparc-ravenscar-thread.h"

  21. static void sparc_ravenscar_fetch_registers (struct regcache *regcache,
  22.                                              int regnum);
  23. static void sparc_ravenscar_store_registers (struct regcache *regcache,
  24.                                              int regnum);
  25. static void sparc_ravenscar_prepare_to_store (struct regcache *regcache);

  26. /* Register offsets from a referenced address (exempli gratia the
  27.    Thread_Descriptor).  The referenced address depends on the register
  28.    number.  The Thread_Descriptor layout and the stack layout are documented
  29.    in the GNAT sources, in sparc-bb.h.  */

  30. static const int sparc_register_offsets[] =
  31. {
  32.   /* G0 - G7 */
  33.   -1,   0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C,
  34.   /* O0 - O7 */
  35.   0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C,
  36.   /* L0 - L7 */
  37.   0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C,
  38.   /* I0 - I7 */
  39.   0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C,
  40.   /* F0 - F31 */
  41.   0x50, 0x54, 0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C,
  42.   0x70, 0x74, 0x78, 0x7C, 0x80, 0x84, 0x88, 0x8C,
  43.   0x90, 0x94, 0x99, 0x9C, 0xA0, 0xA4, 0xA8, 0xAC,
  44.   0xB0, 0xB4, 0xBB, 0xBC, 0xC0, 0xC4, 0xC8, 0xCC,
  45.   /* Y  PSR   WIM   TBR   PC    NPC   FPSR  CPSR */
  46.   0x40, 0x20, 0x44, -1,   0x1C, -1,   0x4C, -1
  47. };

  48. /* supply register REGNUM, which has been saved on REGISTER_ADDR, to the
  49.    regcache.  */

  50. static void
  51. supply_register_at_address (struct regcache *regcache, int regnum,
  52.                             CORE_ADDR register_addr)
  53. {
  54.   struct gdbarch *gdbarch = get_regcache_arch (regcache);
  55.   int buf_size = register_size (gdbarch, regnum);
  56.   gdb_byte *buf;

  57.   buf = alloca (buf_size);
  58.   read_memory (register_addr, buf, buf_size);
  59.   regcache_raw_supply (regcache, regnum, buf);
  60. }

  61. /* Return true if, for a non-running thread, REGNUM has been saved on the
  62.    stack.  */

  63. static int
  64. register_on_stack_p (int regnum)
  65. {
  66.   return (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM)
  67.     || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM);
  68. }

  69. /* Return true if, for a non-running thread, REGNUM has been saved on the
  70.    Thread_Descriptor.  */

  71. static int
  72. register_in_thread_descriptor_p (int regnum)
  73. {
  74.   return (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
  75.     || (regnum == SPARC32_PSR_REGNUM)
  76.     || (regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM)
  77.     || (regnum == SPARC32_Y_REGNUM)
  78.     || (regnum == SPARC32_WIM_REGNUM)
  79.     || (regnum == SPARC32_FSR_REGNUM)
  80.     || (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F0_REGNUM + 31)
  81.     || (regnum == SPARC32_PC_REGNUM);
  82. }

  83. /* to_fetch_registers when inferior_ptid is different from the running
  84.    thread.  */

  85. static void
  86. sparc_ravenscar_fetch_registers (struct regcache *regcache, int regnum)
  87. {
  88.   struct gdbarch *gdbarch = get_regcache_arch (regcache);
  89.   const int sp_regnum = gdbarch_sp_regnum (gdbarch);
  90.   const int num_regs = gdbarch_num_regs (gdbarch);
  91.   int current_regnum;
  92.   CORE_ADDR current_address;
  93.   CORE_ADDR thread_descriptor_address;
  94.   ULONGEST stack_address;

  95.   /* The tid is the thread_id field, which is a pointer to the thread.  */
  96.   thread_descriptor_address = (CORE_ADDR) ptid_get_tid (inferior_ptid);

  97.   /* Read the saved SP in the context buffer.  */
  98.   current_address = thread_descriptor_address
  99.     + sparc_register_offsets [sp_regnum];
  100.   supply_register_at_address (regcache, sp_regnum, current_address);
  101.   regcache_cooked_read_unsigned (regcache, sp_regnum, &stack_address);

  102.   /* Read registers.  */
  103.   for (current_regnum = 0; current_regnum < num_regs; current_regnum ++)
  104.     {
  105.       if (register_in_thread_descriptor_p (current_regnum))
  106.         {
  107.           current_address = thread_descriptor_address
  108.             + sparc_register_offsets [current_regnum];
  109.           supply_register_at_address (regcache, current_regnum,
  110.                                       current_address);
  111.         }
  112.       else if (register_on_stack_p (current_regnum))
  113.         {
  114.           current_address = stack_address
  115.             + sparc_register_offsets [current_regnum];
  116.           supply_register_at_address (regcache, current_regnum,
  117.                                       current_address);
  118.         }
  119.     }
  120. }

  121. /* to_prepare_to_store when inferior_ptid is different from the running
  122.    thread.  */

  123. static void
  124. sparc_ravenscar_prepare_to_store (struct regcache *regcache)
  125. {
  126.   /* Nothing to do.  */
  127. }

  128. /* to_store_registers when inferior_ptid is different from the running
  129.    thread.  */

  130. static void
  131. sparc_ravenscar_store_registers (struct regcache *regcache, int regnum)
  132. {
  133.   struct gdbarch *gdbarch = get_regcache_arch (regcache);
  134.   int buf_size = register_size (gdbarch, regnum);
  135.   gdb_byte buf[buf_size];
  136.   ULONGEST register_address;

  137.   if (register_in_thread_descriptor_p (regnum))
  138.     register_address =
  139.       ptid_get_tid (inferior_ptid) + sparc_register_offsets [regnum];
  140.   else if (register_on_stack_p (regnum))
  141.     {
  142.       regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM,
  143.                                      &register_address);
  144.       register_address += sparc_register_offsets [regnum];
  145.     }
  146.   else
  147.     return;

  148.   regcache_raw_collect (regcache, regnum, buf);
  149.   write_memory (register_address,
  150.                 buf,
  151.                 buf_size);
  152. }

  153. static struct ravenscar_arch_ops sparc_ravenscar_ops =
  154. {
  155.   sparc_ravenscar_fetch_registers,
  156.   sparc_ravenscar_store_registers,
  157.   sparc_ravenscar_prepare_to_store
  158. };

  159. /* Register ravenscar_arch_ops in GDBARCH.  */

  160. void
  161. register_sparc_ravenscar_ops (struct gdbarch *gdbarch)
  162. {
  163.   set_gdbarch_ravenscar_ops (gdbarch, &sparc_ravenscar_ops);
  164. }