GDBserver
|
00001 /* GNU/Linux/Xtensa specific low level interface, for the remote server for GDB. 00002 Copyright (C) 2007-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 00020 #include "server.h" 00021 #include "linux-low.h" 00022 00023 /* Defined in auto-generated file reg-xtensa.c. */ 00024 void init_registers_xtensa (void); 00025 extern const struct target_desc *tdesc_xtensa; 00026 00027 #include <sys/ptrace.h> 00028 #include <xtensa-config.h> 00029 00030 #include "xtensa-xtregs.c" 00031 00032 enum regnum { 00033 R_PC=0, R_PS, 00034 R_LBEG, R_LEND, R_LCOUNT, 00035 R_SAR, 00036 R_WS, R_WB, 00037 R_A0 = 64 00038 }; 00039 00040 static void 00041 xtensa_fill_gregset (struct regcache *regcache, void *buf) 00042 { 00043 elf_greg_t* rset = (elf_greg_t*)buf; 00044 const struct target_desc *tdesc = regcache->tdesc; 00045 int ar0_regnum; 00046 char *ptr; 00047 int i; 00048 00049 /* Take care of AR registers. */ 00050 00051 ar0_regnum = find_regno (tdesc, "ar0"); 00052 ptr = (char*)&rset[R_A0]; 00053 00054 for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++) 00055 { 00056 collect_register (regcache, i, ptr); 00057 ptr += register_size (tdesc, i); 00058 } 00059 00060 /* Loop registers, if hardware has it. */ 00061 00062 #if XCHAL_HAVE_LOOP 00063 collect_register_by_name (regcache, "lbeg", (char*)&rset[R_LBEG]); 00064 collect_register_by_name (regcache, "lend", (char*)&rset[R_LEND]); 00065 collect_register_by_name (regcache, "lcount", (char*)&rset[R_LCOUNT]); 00066 #endif 00067 00068 collect_register_by_name (regcache, "sar", (char*)&rset[R_SAR]); 00069 collect_register_by_name (regcache, "pc", (char*)&rset[R_PC]); 00070 collect_register_by_name (regcache, "ps", (char*)&rset[R_PS]); 00071 collect_register_by_name (regcache, "windowbase", (char*)&rset[R_WB]); 00072 collect_register_by_name (regcache, "windowstart", (char*)&rset[R_WS]); 00073 } 00074 00075 static void 00076 xtensa_store_gregset (struct regcache *regcache, const void *buf) 00077 { 00078 const elf_greg_t* rset = (const elf_greg_t*)buf; 00079 const struct target_desc *tdesc = regcache->tdesc; 00080 int ar0_regnum; 00081 char *ptr; 00082 int i; 00083 00084 /* Take care of AR registers. */ 00085 00086 ar0_regnum = find_regno (tdesc, "ar0"); 00087 ptr = (char *)&rset[R_A0]; 00088 00089 for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++) 00090 { 00091 supply_register (regcache, i, ptr); 00092 ptr += register_size (tdesc, i); 00093 } 00094 00095 /* Loop registers, if hardware has it. */ 00096 00097 #if XCHAL_HAVE_LOOP 00098 supply_register_by_name (regcache, "lbeg", (char*)&rset[R_LBEG]); 00099 supply_register_by_name (regcache, "lend", (char*)&rset[R_LEND]); 00100 supply_register_by_name (regcache, "lcount", (char*)&rset[R_LCOUNT]); 00101 #endif 00102 00103 supply_register_by_name (regcache, "sar", (char*)&rset[R_SAR]); 00104 supply_register_by_name (regcache, "pc", (char*)&rset[R_PC]); 00105 supply_register_by_name (regcache, "ps", (char*)&rset[R_PS]); 00106 supply_register_by_name (regcache, "windowbase", (char*)&rset[R_WB]); 00107 supply_register_by_name (regcache, "windowstart", (char*)&rset[R_WS]); 00108 } 00109 00110 /* Xtensa GNU/Linux PTRACE interface includes extended register set. */ 00111 00112 static void 00113 xtensa_fill_xtregset (struct regcache *regcache, void *buf) 00114 { 00115 const xtensa_regtable_t *ptr; 00116 00117 for (ptr = xtensa_regmap_table; ptr->name; ptr++) 00118 { 00119 collect_register_by_name (regcache, ptr->name, 00120 (char*)buf + ptr->ptrace_offset); 00121 } 00122 } 00123 00124 static void 00125 xtensa_store_xtregset (struct regcache *regcache, const void *buf) 00126 { 00127 const xtensa_regtable_t *ptr; 00128 00129 for (ptr = xtensa_regmap_table; ptr->name; ptr++) 00130 { 00131 supply_register_by_name (regcache, ptr->name, 00132 (char*)buf + ptr->ptrace_offset); 00133 } 00134 } 00135 00136 static struct regset_info xtensa_regsets[] = { 00137 { PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t), 00138 GENERAL_REGS, 00139 xtensa_fill_gregset, xtensa_store_gregset }, 00140 { PTRACE_GETXTREGS, PTRACE_SETXTREGS, 0, XTENSA_ELF_XTREG_SIZE, 00141 EXTENDED_REGS, 00142 xtensa_fill_xtregset, xtensa_store_xtregset }, 00143 { 0, 0, 0, -1, -1, NULL, NULL } 00144 }; 00145 00146 #if XCHAL_HAVE_BE 00147 #define XTENSA_BREAKPOINT {0xd2,0x0f} 00148 #else 00149 #define XTENSA_BREAKPOINT {0x2d,0xf0} 00150 #endif 00151 00152 static const unsigned char xtensa_breakpoint[] = XTENSA_BREAKPOINT; 00153 #define xtensa_breakpoint_len 2 00154 00155 static CORE_ADDR 00156 xtensa_get_pc (struct regcache *regcache) 00157 { 00158 unsigned long pc; 00159 00160 collect_register_by_name (regcache, "pc", &pc); 00161 return pc; 00162 } 00163 00164 static void 00165 xtensa_set_pc (struct regcache *regcache, CORE_ADDR pc) 00166 { 00167 unsigned long newpc = pc; 00168 supply_register_by_name (regcache, "pc", &newpc); 00169 } 00170 00171 static int 00172 xtensa_breakpoint_at (CORE_ADDR where) 00173 { 00174 unsigned long insn; 00175 00176 (*the_target->read_memory) (where, (unsigned char *) &insn, 00177 xtensa_breakpoint_len); 00178 return memcmp((char *) &insn, 00179 xtensa_breakpoint, xtensa_breakpoint_len) == 0; 00180 } 00181 00182 static struct regsets_info xtensa_regsets_info = 00183 { 00184 xtensa_regsets, /* regsets */ 00185 0, /* num_regsets */ 00186 NULL, /* disabled_regsets */ 00187 }; 00188 00189 static struct usrregs_info xtensa_usrregs_info = 00190 { 00191 xtensa_num_regs, 00192 xtensa_regmap, 00193 }; 00194 00195 static struct regs_info regs_info = 00196 { 00197 NULL, /* regset_bitmap */ 00198 &xtensa_usrregs_info, 00199 &xtensa_regsets_info 00200 }; 00201 00202 static void 00203 xtensa_arch_setup (void) 00204 { 00205 current_process ()->tdesc = tdesc_xtensa; 00206 } 00207 00208 static const struct regs_info * 00209 xtensa_regs_info (void) 00210 { 00211 return ®s_info; 00212 } 00213 00214 struct linux_target_ops the_low_target = { 00215 xtensa_arch_setup, 00216 xtensa_regs_info, 00217 0, 00218 0, 00219 NULL, /* fetch_register */ 00220 xtensa_get_pc, 00221 xtensa_set_pc, 00222 xtensa_breakpoint, 00223 xtensa_breakpoint_len, 00224 NULL, 00225 0, 00226 xtensa_breakpoint_at, 00227 }; 00228 00229 00230 void 00231 initialize_low_arch (void) 00232 { 00233 /* Initialize the Linux target descriptions. */ 00234 init_registers_xtensa (); 00235 00236 initialize_regsets_info (&xtensa_regsets_info); 00237 }