Home | History | Annotate | Line # | Download | only in gdbserver
      1 /* GNU/Linux/SH specific low level interface, for the remote server for GDB.
      2    Copyright (C) 1995-2024 Free Software Foundation, Inc.
      3 
      4    This file is part of GDB.
      5 
      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 
     11    This program is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     18 
     19 #include "linux-low.h"
     20 
     21 /* Linux target op definitions for the SH architecture.  */
     22 
     23 class sh_target : public linux_process_target
     24 {
     25 public:
     26 
     27   const regs_info *get_regs_info () override;
     28 
     29   const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override;
     30 
     31 protected:
     32 
     33   void low_arch_setup () override;
     34 
     35   bool low_cannot_fetch_register (int regno) override;
     36 
     37   bool low_cannot_store_register (int regno) override;
     38 
     39   bool low_supports_breakpoints () override;
     40 
     41   CORE_ADDR low_get_pc (regcache *regcache) override;
     42 
     43   void low_set_pc (regcache *regcache, CORE_ADDR newpc) override;
     44 
     45   bool low_breakpoint_at (CORE_ADDR pc) override;
     46 };
     47 
     48 /* The singleton target ops object.  */
     49 
     50 static sh_target the_sh_target;
     51 
     52 bool
     53 sh_target::low_supports_breakpoints ()
     54 {
     55   return true;
     56 }
     57 
     58 CORE_ADDR
     59 sh_target::low_get_pc (regcache *regcache)
     60 {
     61   return linux_get_pc_32bit (regcache);
     62 }
     63 
     64 void
     65 sh_target::low_set_pc (regcache *regcache, CORE_ADDR pc)
     66 {
     67   linux_set_pc_32bit (regcache, pc);
     68 }
     69 
     70 /* Defined in auto-generated file reg-sh.c.  */
     71 void init_registers_sh (void);
     72 extern const struct target_desc *tdesc_sh;
     73 
     74 #ifdef HAVE_SYS_REG_H
     75 #include <sys/reg.h>
     76 #endif
     77 
     78 #include <asm/ptrace.h>
     79 
     80 #define sh_num_regs 41
     81 
     82 /* Currently, don't check/send MQ.  */
     83 static int sh_regmap[] = {
     84  0,	4,	8,	12,	16,	20,	24,	28,
     85  32,	36,	40,	44,	48,	52,	56,	60,
     86 
     87  REG_PC*4,   REG_PR*4,   REG_GBR*4,  -1,
     88  REG_MACH*4, REG_MACL*4, REG_SR*4,
     89  REG_FPUL*4, REG_FPSCR*4,
     90 
     91  REG_FPREG0*4+0,   REG_FPREG0*4+4,   REG_FPREG0*4+8,   REG_FPREG0*4+12,
     92  REG_FPREG0*4+16,  REG_FPREG0*4+20,  REG_FPREG0*4+24,  REG_FPREG0*4+28,
     93  REG_FPREG0*4+32,  REG_FPREG0*4+36,  REG_FPREG0*4+40,  REG_FPREG0*4+44,
     94  REG_FPREG0*4+48,  REG_FPREG0*4+52,  REG_FPREG0*4+56,  REG_FPREG0*4+60,
     95 };
     96 
     97 bool
     98 sh_target::low_cannot_store_register (int regno)
     99 {
    100   return false;
    101 }
    102 
    103 bool
    104 sh_target::low_cannot_fetch_register (int regno)
    105 {
    106   return false;
    107 }
    108 
    109 /* Correct in either endianness, obviously.  */
    110 static const unsigned short sh_breakpoint = 0xc3c3;
    111 #define sh_breakpoint_len 2
    112 
    113 /* Implementation of target ops method "sw_breakpoint_from_kind".  */
    114 
    115 const gdb_byte *
    116 sh_target::sw_breakpoint_from_kind (int kind, int *size)
    117 {
    118   *size = sh_breakpoint_len;
    119   return (const gdb_byte *) &sh_breakpoint;
    120 }
    121 
    122 bool
    123 sh_target::low_breakpoint_at (CORE_ADDR where)
    124 {
    125   unsigned short insn;
    126 
    127   read_memory (where, (unsigned char *) &insn, 2);
    128   if (insn == sh_breakpoint)
    129     return true;
    130 
    131   /* If necessary, recognize more trap instructions here.  GDB only uses the
    132      one.  */
    133   return false;
    134 }
    135 
    136 /* Provide only a fill function for the general register set.  ps_lgetregs
    137    will use this for NPTL support.  */
    138 
    139 static void sh_fill_gregset (struct regcache *regcache, void *buf)
    140 {
    141   int i;
    142 
    143   for (i = 0; i < 23; i++)
    144     if (sh_regmap[i] != -1)
    145       collect_register (regcache, i, (char *) buf + sh_regmap[i]);
    146 }
    147 
    148 static struct regset_info sh_regsets[] = {
    149   { 0, 0, 0, 0, GENERAL_REGS, sh_fill_gregset, NULL },
    150   NULL_REGSET
    151 };
    152 
    153 static struct regsets_info sh_regsets_info =
    154   {
    155     sh_regsets, /* regsets */
    156     0, /* num_regsets */
    157     NULL, /* disabled_regsets */
    158   };
    159 
    160 static struct usrregs_info sh_usrregs_info =
    161   {
    162     sh_num_regs,
    163     sh_regmap,
    164   };
    165 
    166 static struct regs_info myregs_info =
    167   {
    168     NULL, /* regset_bitmap */
    169     &sh_usrregs_info,
    170     &sh_regsets_info
    171   };
    172 
    173 const regs_info *
    174 sh_target::get_regs_info ()
    175 {
    176   return &myregs_info;
    177 }
    178 
    179 void
    180 sh_target::low_arch_setup ()
    181 {
    182   current_process ()->tdesc = tdesc_sh;
    183 }
    184 
    185 /* The linux target ops object.  */
    186 
    187 linux_process_target *the_linux_target = &the_sh_target;
    188 
    189 void
    190 initialize_low_arch (void)
    191 {
    192   init_registers_sh ();
    193 
    194   initialize_regsets_info (&sh_regsets_info);
    195 }
    196