xref: /netbsd-src/external/gpl3/gdb/dist/gdbserver/linux-sparc-low.cc (revision 13ed34fa5696ce1ff8e9519eeb5619eee4331db8)
18dffb485Schristos /* Low level interface to ptrace, for the remote server for GDB.
2*13ed34faSchristos    Copyright (C) 1995-2024 Free Software Foundation, Inc.
38dffb485Schristos 
48dffb485Schristos    This file is part of GDB.
58dffb485Schristos 
68dffb485Schristos    This program is free software; you can redistribute it and/or modify
78dffb485Schristos    it under the terms of the GNU General Public License as published by
88dffb485Schristos    the Free Software Foundation; either version 3 of the License, or
98dffb485Schristos    (at your option) any later version.
108dffb485Schristos 
118dffb485Schristos    This program is distributed in the hope that it will be useful,
128dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
138dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
148dffb485Schristos    GNU General Public License for more details.
158dffb485Schristos 
168dffb485Schristos    You should have received a copy of the GNU General Public License
178dffb485Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
188dffb485Schristos 
198dffb485Schristos #include "linux-low.h"
208dffb485Schristos 
218dffb485Schristos #include "nat/gdb_ptrace.h"
228dffb485Schristos 
238dffb485Schristos #include "gdb_proc_service.h"
248dffb485Schristos 
258dffb485Schristos /* The stack pointer is offset from the stack frame by a BIAS of 2047
268dffb485Schristos    (0x7ff) for 64-bit code.  BIAS is likely to be defined on SPARC
278dffb485Schristos    hosts, so undefine it first.  */
288dffb485Schristos #undef BIAS
298dffb485Schristos #define BIAS 2047
308dffb485Schristos 
318dffb485Schristos #ifdef HAVE_SYS_REG_H
328dffb485Schristos #include <sys/reg.h>
338dffb485Schristos #endif
348dffb485Schristos 
358dffb485Schristos #define INSN_SIZE 4
368dffb485Schristos 
378dffb485Schristos #define SPARC_R_REGS_NUM 32
388dffb485Schristos #define SPARC_F_REGS_NUM 48
398dffb485Schristos #define SPARC_CONTROL_REGS_NUM 6
408dffb485Schristos 
418dffb485Schristos #define sparc_num_regs \
428dffb485Schristos   (SPARC_R_REGS_NUM + SPARC_F_REGS_NUM + SPARC_CONTROL_REGS_NUM)
438dffb485Schristos 
448dffb485Schristos /* Linux target op definitions for the SPARC architecture.  */
458dffb485Schristos 
468dffb485Schristos class sparc_target : public linux_process_target
478dffb485Schristos {
488dffb485Schristos public:
498dffb485Schristos 
508dffb485Schristos   const regs_info *get_regs_info () override;
518dffb485Schristos 
528dffb485Schristos   const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override;
538dffb485Schristos 
548dffb485Schristos protected:
558dffb485Schristos 
568dffb485Schristos   void low_arch_setup () override;
578dffb485Schristos 
588dffb485Schristos   bool low_cannot_fetch_register (int regno) override;
598dffb485Schristos 
608dffb485Schristos   bool low_cannot_store_register (int regno) override;
618dffb485Schristos 
628dffb485Schristos   bool low_supports_breakpoints () override;
638dffb485Schristos 
648dffb485Schristos   CORE_ADDR low_get_pc (regcache *regcache) override;
658dffb485Schristos 
668dffb485Schristos   /* No low_set_pc is needed.  */
678dffb485Schristos 
688dffb485Schristos   bool low_breakpoint_at (CORE_ADDR pc) override;
698dffb485Schristos };
708dffb485Schristos 
718dffb485Schristos /* The singleton target ops object.  */
728dffb485Schristos 
738dffb485Schristos static sparc_target the_sparc_target;
748dffb485Schristos 
758dffb485Schristos bool
768dffb485Schristos sparc_target::low_supports_breakpoints ()
778dffb485Schristos {
788dffb485Schristos   return true;
798dffb485Schristos }
808dffb485Schristos 
818dffb485Schristos CORE_ADDR
828dffb485Schristos sparc_target::low_get_pc (regcache *regcache)
838dffb485Schristos {
848dffb485Schristos   return linux_get_pc_64bit (regcache);
858dffb485Schristos }
868dffb485Schristos 
878dffb485Schristos /* Each offset is multiplied by 8, because of the register size.
888dffb485Schristos    These offsets apply to the buffer sent/filled by ptrace.
898dffb485Schristos    Additionally, the array elements order corresponds to the .dat file, and the
908dffb485Schristos    gdb's registers enumeration order.  */
918dffb485Schristos 
928dffb485Schristos static int sparc_regmap[] = {
938dffb485Schristos   /* These offsets correspond to GET/SETREGSET.  */
948dffb485Schristos 	-1,  0*8,  1*8,  2*8,  3*8,  4*8,  5*8,  6*8,	 /* g0 .. g7 */
958dffb485Schristos 	7*8,  8*8,  9*8, 10*8, 11*8, 12*8, 13*8, 14*8,	 /* o0 .. o5, sp, o7 */
968dffb485Schristos 	-1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,	 /* l0 .. l7 */
978dffb485Schristos 	-1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,	 /* i0 .. i5, fp, i7 */
988dffb485Schristos 
998dffb485Schristos   /* Floating point registers offsets correspond to GET/SETFPREGSET.  */
1008dffb485Schristos     0*4,  1*4,  2*4,  3*4,  4*4,  5*4,  6*4,  7*4,	   /*  f0 ..  f7 */
1018dffb485Schristos     8*4,  9*4, 10*4, 11*4, 12*4, 13*4, 14*4, 15*4,	   /*  f8 .. f15 */
1028dffb485Schristos    16*4, 17*4, 18*4, 19*4, 20*4, 21*4, 22*4, 23*4,	   /* f16 .. f23 */
1038dffb485Schristos    24*4, 25*4, 26*4, 27*4, 28*4, 29*4, 30*4, 31*4,	   /* f24 .. f31 */
1048dffb485Schristos 
1058dffb485Schristos   /* F32 offset starts next to f31: 31*4+4 = 16 * 8.  */
1068dffb485Schristos    16*8, 17*8, 18*8, 19*8, 20*8, 21*8, 22*8, 23*8,	   /* f32 .. f46 */
1078dffb485Schristos    24*8, 25*8, 26*8, 27*8, 28*8, 29*8, 30*8, 31*8,	   /* f48 .. f62 */
1088dffb485Schristos 
1098dffb485Schristos    17 *8, /*    pc */
1108dffb485Schristos    18 *8, /*   npc */
1118dffb485Schristos    16 *8, /* state */
1128dffb485Schristos   /* FSR offset also corresponds to GET/SETFPREGSET, ans is placed
1138dffb485Schristos      next to f62.  */
1148dffb485Schristos    32 *8, /*   fsr */
1158dffb485Schristos       -1, /*  fprs */
1168dffb485Schristos   /* Y register is 32-bits length, but gdb takes care of that.  */
1178dffb485Schristos    19 *8, /*     y */
1188dffb485Schristos 
1198dffb485Schristos };
1208dffb485Schristos 
1218dffb485Schristos 
1228dffb485Schristos struct regs_range_t
1238dffb485Schristos {
1248dffb485Schristos   int regno_start;
1258dffb485Schristos   int regno_end;
1268dffb485Schristos };
1278dffb485Schristos 
1288dffb485Schristos static const struct regs_range_t gregs_ranges[] = {
1298dffb485Schristos  {  0, 31 }, /*   g0 .. i7  */
1308dffb485Schristos  { 80, 82 }, /*   pc .. state */
1318dffb485Schristos  { 84, 85 }  /* fprs .. y */
1328dffb485Schristos };
1338dffb485Schristos 
1348dffb485Schristos #define N_GREGS_RANGES (sizeof (gregs_ranges) / sizeof (struct regs_range_t))
1358dffb485Schristos 
1368dffb485Schristos static const struct regs_range_t fpregs_ranges[] = {
1378dffb485Schristos  { 32, 79 }, /* f0 .. f62  */
1388dffb485Schristos  { 83, 83 }  /* fsr */
1398dffb485Schristos };
1408dffb485Schristos 
1418dffb485Schristos #define N_FPREGS_RANGES (sizeof (fpregs_ranges) / sizeof (struct regs_range_t))
1428dffb485Schristos 
1438dffb485Schristos /* Defined in auto-generated file reg-sparc64.c.  */
1448dffb485Schristos void init_registers_sparc64 (void);
1458dffb485Schristos extern const struct target_desc *tdesc_sparc64;
1468dffb485Schristos 
1478dffb485Schristos bool
1488dffb485Schristos sparc_target::low_cannot_store_register (int regno)
1498dffb485Schristos {
1508dffb485Schristos   return (regno >= sparc_num_regs || sparc_regmap[regno] == -1);
1518dffb485Schristos }
1528dffb485Schristos 
1538dffb485Schristos bool
1548dffb485Schristos sparc_target::low_cannot_fetch_register (int regno)
1558dffb485Schristos {
1568dffb485Schristos   return (regno >= sparc_num_regs || sparc_regmap[regno] == -1);
1578dffb485Schristos }
1588dffb485Schristos 
1598dffb485Schristos static void
1608dffb485Schristos sparc_fill_gregset_to_stack (struct regcache *regcache, const void *buf)
1618dffb485Schristos {
1628dffb485Schristos   int i;
1638dffb485Schristos   CORE_ADDR addr = 0;
1648dffb485Schristos   unsigned char tmp_reg_buf[8];
1658dffb485Schristos   const int l0_regno = find_regno (regcache->tdesc, "l0");
1668dffb485Schristos   const int i7_regno = l0_regno + 15;
1678dffb485Schristos 
1688dffb485Schristos   /* These registers have to be stored in the stack.  */
1698dffb485Schristos   memcpy (&addr,
1708dffb485Schristos 	  ((char *) buf) + sparc_regmap[find_regno (regcache->tdesc, "sp")],
1718dffb485Schristos 	  sizeof (addr));
1728dffb485Schristos 
1738dffb485Schristos   addr += BIAS;
1748dffb485Schristos 
1758dffb485Schristos   for (i = l0_regno; i <= i7_regno; i++)
1768dffb485Schristos     {
1778dffb485Schristos       collect_register (regcache, i, tmp_reg_buf);
1788dffb485Schristos       the_target->write_memory (addr, tmp_reg_buf, sizeof (tmp_reg_buf));
1798dffb485Schristos       addr += sizeof (tmp_reg_buf);
1808dffb485Schristos     }
1818dffb485Schristos }
1828dffb485Schristos 
1838dffb485Schristos static void
1848dffb485Schristos sparc_fill_gregset (struct regcache *regcache, void *buf)
1858dffb485Schristos {
1868dffb485Schristos   int i;
1878dffb485Schristos   int range;
1888dffb485Schristos 
1898dffb485Schristos   for (range = 0; range < N_GREGS_RANGES; range++)
1908dffb485Schristos     for (i = gregs_ranges[range].regno_start;
1918dffb485Schristos 	 i <= gregs_ranges[range].regno_end; i++)
1928dffb485Schristos       if (sparc_regmap[i] != -1)
1938dffb485Schristos 	collect_register (regcache, i, ((char *) buf) + sparc_regmap[i]);
1948dffb485Schristos 
1958dffb485Schristos   sparc_fill_gregset_to_stack (regcache, buf);
1968dffb485Schristos }
1978dffb485Schristos 
1988dffb485Schristos static void
1998dffb485Schristos sparc_fill_fpregset (struct regcache *regcache, void *buf)
2008dffb485Schristos {
2018dffb485Schristos   int i;
2028dffb485Schristos   int range;
2038dffb485Schristos 
2048dffb485Schristos   for (range = 0; range < N_FPREGS_RANGES; range++)
2058dffb485Schristos     for (i = fpregs_ranges[range].regno_start;
2068dffb485Schristos 	 i <= fpregs_ranges[range].regno_end; i++)
2078dffb485Schristos       collect_register (regcache, i, ((char *) buf) + sparc_regmap[i]);
2088dffb485Schristos 
2098dffb485Schristos }
2108dffb485Schristos 
2118dffb485Schristos static void
2128dffb485Schristos sparc_store_gregset_from_stack (struct regcache *regcache, const void *buf)
2138dffb485Schristos {
2148dffb485Schristos   int i;
2158dffb485Schristos   CORE_ADDR addr = 0;
2168dffb485Schristos   unsigned char tmp_reg_buf[8];
2178dffb485Schristos   const int l0_regno = find_regno (regcache->tdesc, "l0");
2188dffb485Schristos   const int i7_regno = l0_regno + 15;
2198dffb485Schristos 
2208dffb485Schristos   /* These registers have to be obtained from the stack.  */
2218dffb485Schristos   memcpy (&addr,
2228dffb485Schristos 	  ((char *) buf) + sparc_regmap[find_regno (regcache->tdesc, "sp")],
2238dffb485Schristos 	  sizeof (addr));
2248dffb485Schristos 
2258dffb485Schristos   addr += BIAS;
2268dffb485Schristos 
2278dffb485Schristos   for (i = l0_regno; i <= i7_regno; i++)
2288dffb485Schristos     {
2298dffb485Schristos       the_target->read_memory (addr, tmp_reg_buf, sizeof (tmp_reg_buf));
2308dffb485Schristos       supply_register (regcache, i, tmp_reg_buf);
2318dffb485Schristos       addr += sizeof (tmp_reg_buf);
2328dffb485Schristos     }
2338dffb485Schristos }
2348dffb485Schristos 
2358dffb485Schristos static void
2368dffb485Schristos sparc_store_gregset (struct regcache *regcache, const void *buf)
2378dffb485Schristos {
2388dffb485Schristos   int i;
2398dffb485Schristos   char zerobuf[8];
2408dffb485Schristos   int range;
2418dffb485Schristos 
2428dffb485Schristos   memset (zerobuf, 0, sizeof (zerobuf));
2438dffb485Schristos 
2448dffb485Schristos   for (range = 0; range < N_GREGS_RANGES; range++)
2458dffb485Schristos     for (i = gregs_ranges[range].regno_start;
2468dffb485Schristos 	 i <= gregs_ranges[range].regno_end; i++)
2478dffb485Schristos       if (sparc_regmap[i] != -1)
2488dffb485Schristos 	supply_register (regcache, i, ((char *) buf) + sparc_regmap[i]);
2498dffb485Schristos       else
2508dffb485Schristos 	supply_register (regcache, i, zerobuf);
2518dffb485Schristos 
2528dffb485Schristos   sparc_store_gregset_from_stack (regcache, buf);
2538dffb485Schristos }
2548dffb485Schristos 
2558dffb485Schristos static void
2568dffb485Schristos sparc_store_fpregset (struct regcache *regcache, const void *buf)
2578dffb485Schristos {
2588dffb485Schristos   int i;
2598dffb485Schristos   int range;
2608dffb485Schristos 
2618dffb485Schristos   for (range = 0; range < N_FPREGS_RANGES; range++)
2628dffb485Schristos     for (i = fpregs_ranges[range].regno_start;
2638dffb485Schristos 	 i <= fpregs_ranges[range].regno_end;
2648dffb485Schristos 	 i++)
2658dffb485Schristos       supply_register (regcache, i, ((char *) buf) + sparc_regmap[i]);
2668dffb485Schristos }
2678dffb485Schristos 
2688dffb485Schristos static const gdb_byte sparc_breakpoint[INSN_SIZE] = {
2698dffb485Schristos   0x91, 0xd0, 0x20, 0x01
2708dffb485Schristos };
2718dffb485Schristos #define sparc_breakpoint_len INSN_SIZE
2728dffb485Schristos 
2738dffb485Schristos /* Implementation of target ops method "sw_breakpoint_from_kind".  */
2748dffb485Schristos 
2758dffb485Schristos const gdb_byte *
2768dffb485Schristos sparc_target::sw_breakpoint_from_kind (int kind, int *size)
2778dffb485Schristos {
2788dffb485Schristos   *size = sparc_breakpoint_len;
2798dffb485Schristos   return sparc_breakpoint;
2808dffb485Schristos }
2818dffb485Schristos 
2828dffb485Schristos bool
2838dffb485Schristos sparc_target::low_breakpoint_at (CORE_ADDR where)
2848dffb485Schristos {
2858dffb485Schristos   unsigned char insn[INSN_SIZE];
2868dffb485Schristos 
2878dffb485Schristos   read_memory (where, (unsigned char *) insn, sizeof (insn));
2888dffb485Schristos 
2898dffb485Schristos   if (memcmp (sparc_breakpoint, insn, sizeof (insn)) == 0)
2908dffb485Schristos     return true;
2918dffb485Schristos 
2928dffb485Schristos   /* If necessary, recognize more trap instructions here.  GDB only
2938dffb485Schristos      uses TRAP Always.  */
2948dffb485Schristos 
2958dffb485Schristos   return false;
2968dffb485Schristos }
2978dffb485Schristos 
2988dffb485Schristos void
2998dffb485Schristos sparc_target::low_arch_setup ()
3008dffb485Schristos {
3018dffb485Schristos   current_process ()->tdesc = tdesc_sparc64;
3028dffb485Schristos }
3038dffb485Schristos 
3048dffb485Schristos static struct regset_info sparc_regsets[] = {
3058dffb485Schristos   { PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
3068dffb485Schristos     GENERAL_REGS,
3078dffb485Schristos     sparc_fill_gregset, sparc_store_gregset },
3088dffb485Schristos   { PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, sizeof (fpregset_t),
3098dffb485Schristos     FP_REGS,
3108dffb485Schristos     sparc_fill_fpregset, sparc_store_fpregset },
3118dffb485Schristos   NULL_REGSET
3128dffb485Schristos };
3138dffb485Schristos 
3148dffb485Schristos static struct regsets_info sparc_regsets_info =
3158dffb485Schristos   {
3168dffb485Schristos     sparc_regsets, /* regsets */
3178dffb485Schristos     0, /* num_regsets */
3188dffb485Schristos     NULL, /* disabled_regsets */
3198dffb485Schristos   };
3208dffb485Schristos 
3218dffb485Schristos static struct usrregs_info sparc_usrregs_info =
3228dffb485Schristos   {
3238dffb485Schristos     sparc_num_regs,
3248dffb485Schristos     /* No regmap needs to be provided since this impl. doesn't use
3258dffb485Schristos        USRREGS.  */
3268dffb485Schristos     NULL
3278dffb485Schristos   };
3288dffb485Schristos 
3298dffb485Schristos static struct regs_info myregs_info =
3308dffb485Schristos   {
3318dffb485Schristos     NULL, /* regset_bitmap */
3328dffb485Schristos     &sparc_usrregs_info,
3338dffb485Schristos     &sparc_regsets_info
3348dffb485Schristos   };
3358dffb485Schristos 
3368dffb485Schristos const regs_info *
3378dffb485Schristos sparc_target::get_regs_info ()
3388dffb485Schristos {
3398dffb485Schristos   return &myregs_info;
3408dffb485Schristos }
3418dffb485Schristos 
3428dffb485Schristos /* The linux target ops object.  */
3438dffb485Schristos 
3448dffb485Schristos linux_process_target *the_linux_target = &the_sparc_target;
3458dffb485Schristos 
3468dffb485Schristos void
3478dffb485Schristos initialize_low_arch (void)
3488dffb485Schristos {
3498dffb485Schristos   /* Initialize the Linux target descriptions.  */
3508dffb485Schristos   init_registers_sparc64 ();
3518dffb485Schristos 
3528dffb485Schristos   initialize_regsets_info (&sparc_regsets_info);
3538dffb485Schristos }
354