GDBserver
|
00001 /* GNU/Linux/SH specific low level interface, for the remote server for GDB. 00002 Copyright (C) 1995-2013 Free Software Foundation, Inc. 00003 00004 This file is part of GDB. 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00018 00019 #include "server.h" 00020 #include "linux-low.h" 00021 00022 /* Defined in auto-generated file reg-sh.c. */ 00023 void init_registers_sh (void); 00024 extern const struct target_desc *tdesc_sh; 00025 00026 #ifdef HAVE_SYS_REG_H 00027 #include <sys/reg.h> 00028 #endif 00029 00030 #include <asm/ptrace.h> 00031 00032 #define sh_num_regs 41 00033 00034 /* Currently, don't check/send MQ. */ 00035 static int sh_regmap[] = { 00036 0, 4, 8, 12, 16, 20, 24, 28, 00037 32, 36, 40, 44, 48, 52, 56, 60, 00038 00039 REG_PC*4, REG_PR*4, REG_GBR*4, -1, 00040 REG_MACH*4, REG_MACL*4, REG_SR*4, 00041 REG_FPUL*4, REG_FPSCR*4, 00042 00043 REG_FPREG0*4+0, REG_FPREG0*4+4, REG_FPREG0*4+8, REG_FPREG0*4+12, 00044 REG_FPREG0*4+16, REG_FPREG0*4+20, REG_FPREG0*4+24, REG_FPREG0*4+28, 00045 REG_FPREG0*4+32, REG_FPREG0*4+36, REG_FPREG0*4+40, REG_FPREG0*4+44, 00046 REG_FPREG0*4+48, REG_FPREG0*4+52, REG_FPREG0*4+56, REG_FPREG0*4+60, 00047 }; 00048 00049 static int 00050 sh_cannot_store_register (int regno) 00051 { 00052 return 0; 00053 } 00054 00055 static int 00056 sh_cannot_fetch_register (int regno) 00057 { 00058 return 0; 00059 } 00060 00061 static CORE_ADDR 00062 sh_get_pc (struct regcache *regcache) 00063 { 00064 unsigned long pc; 00065 collect_register_by_name (regcache, "pc", &pc); 00066 return pc; 00067 } 00068 00069 static void 00070 sh_set_pc (struct regcache *regcache, CORE_ADDR pc) 00071 { 00072 unsigned long newpc = pc; 00073 supply_register_by_name (regcache, "pc", &newpc); 00074 } 00075 00076 /* Correct in either endianness, obviously. */ 00077 static const unsigned short sh_breakpoint = 0xc3c3; 00078 #define sh_breakpoint_len 2 00079 00080 static int 00081 sh_breakpoint_at (CORE_ADDR where) 00082 { 00083 unsigned short insn; 00084 00085 (*the_target->read_memory) (where, (unsigned char *) &insn, 2); 00086 if (insn == sh_breakpoint) 00087 return 1; 00088 00089 /* If necessary, recognize more trap instructions here. GDB only uses the 00090 one. */ 00091 return 0; 00092 } 00093 00094 /* Provide only a fill function for the general register set. ps_lgetregs 00095 will use this for NPTL support. */ 00096 00097 static void sh_fill_gregset (struct regcache *regcache, void *buf) 00098 { 00099 int i; 00100 00101 for (i = 0; i < 23; i++) 00102 if (sh_regmap[i] != -1) 00103 collect_register (regcache, i, (char *) buf + sh_regmap[i]); 00104 } 00105 00106 static struct regset_info sh_regsets[] = { 00107 { 0, 0, 0, 0, GENERAL_REGS, sh_fill_gregset, NULL }, 00108 { 0, 0, 0, -1, -1, NULL, NULL } 00109 }; 00110 00111 static struct regsets_info sh_regsets_info = 00112 { 00113 sh_regsets, /* regsets */ 00114 0, /* num_regsets */ 00115 NULL, /* disabled_regsets */ 00116 }; 00117 00118 static struct usrregs_info sh_usrregs_info = 00119 { 00120 sh_num_regs, 00121 sh_regmap, 00122 }; 00123 00124 static struct regs_info regs_info = 00125 { 00126 NULL, /* regset_bitmap */ 00127 &sh_usrregs_info, 00128 &sh_regsets_info 00129 }; 00130 00131 static const struct regs_info * 00132 sh_regs_info (void) 00133 { 00134 return ®s_info; 00135 } 00136 00137 static void 00138 sh_arch_setup (void) 00139 { 00140 current_process ()->tdesc = tdesc_sh; 00141 } 00142 00143 struct linux_target_ops the_low_target = { 00144 sh_arch_setup, 00145 sh_regs_info, 00146 sh_cannot_fetch_register, 00147 sh_cannot_store_register, 00148 NULL, /* fetch_register */ 00149 sh_get_pc, 00150 sh_set_pc, 00151 (const unsigned char *) &sh_breakpoint, 00152 sh_breakpoint_len, 00153 NULL, 00154 0, 00155 sh_breakpoint_at, 00156 }; 00157 00158 void 00159 initialize_low_arch (void) 00160 { 00161 init_registers_sh (); 00162 00163 initialize_regsets_info (&sh_regsets_info); 00164 }