GDBserver
linux-xtensa-low.c
Go to the documentation of this file.
1 /* GNU/Linux/Xtensa specific low level interface, for the remote server for GDB.
2  Copyright (C) 2007-2015 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 
20 #include "server.h"
21 #include "linux-low.h"
22 
23 /* Defined in auto-generated file reg-xtensa.c. */
24 void init_registers_xtensa (void);
25 extern const struct target_desc *tdesc_xtensa;
26 
27 #include <asm/ptrace.h>
28 #include <xtensa-config.h>
29 
30 #include "xtensa-xtregs.c"
31 
32 enum regnum {
33  R_PC=0, R_PS,
37  R_A0 = 64
38 };
39 
40 static void
42 {
43  elf_greg_t* rset = (elf_greg_t*)buf;
44  const struct target_desc *tdesc = regcache->tdesc;
45  int ar0_regnum;
46  char *ptr;
47  int i;
48 
49  /* Take care of AR registers. */
50 
51  ar0_regnum = find_regno (tdesc, "ar0");
52  ptr = (char*)&rset[R_A0];
53 
54  for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++)
55  {
56  collect_register (regcache, i, ptr);
57  ptr += register_size (tdesc, i);
58  }
59 
60  /* Loop registers, if hardware has it. */
61 
62 #if XCHAL_HAVE_LOOPS
63  collect_register_by_name (regcache, "lbeg", (char*)&rset[R_LBEG]);
64  collect_register_by_name (regcache, "lend", (char*)&rset[R_LEND]);
65  collect_register_by_name (regcache, "lcount", (char*)&rset[R_LCOUNT]);
66 #endif
67 
68  collect_register_by_name (regcache, "sar", (char*)&rset[R_SAR]);
69  collect_register_by_name (regcache, "pc", (char*)&rset[R_PC]);
70  collect_register_by_name (regcache, "ps", (char*)&rset[R_PS]);
71  collect_register_by_name (regcache, "windowbase", (char*)&rset[R_WB]);
72  collect_register_by_name (regcache, "windowstart", (char*)&rset[R_WS]);
73 }
74 
75 static void
76 xtensa_store_gregset (struct regcache *regcache, const void *buf)
77 {
78  const elf_greg_t* rset = (const elf_greg_t*)buf;
79  const struct target_desc *tdesc = regcache->tdesc;
80  int ar0_regnum;
81  char *ptr;
82  int i;
83 
84  /* Take care of AR registers. */
85 
86  ar0_regnum = find_regno (tdesc, "ar0");
87  ptr = (char *)&rset[R_A0];
88 
89  for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++)
90  {
91  supply_register (regcache, i, ptr);
92  ptr += register_size (tdesc, i);
93  }
94 
95  /* Loop registers, if hardware has it. */
96 
97 #if XCHAL_HAVE_LOOPS
98  supply_register_by_name (regcache, "lbeg", (char*)&rset[R_LBEG]);
99  supply_register_by_name (regcache, "lend", (char*)&rset[R_LEND]);
100  supply_register_by_name (regcache, "lcount", (char*)&rset[R_LCOUNT]);
101 #endif
102 
103  supply_register_by_name (regcache, "sar", (char*)&rset[R_SAR]);
104  supply_register_by_name (regcache, "pc", (char*)&rset[R_PC]);
105  supply_register_by_name (regcache, "ps", (char*)&rset[R_PS]);
106  supply_register_by_name (regcache, "windowbase", (char*)&rset[R_WB]);
107  supply_register_by_name (regcache, "windowstart", (char*)&rset[R_WS]);
108 }
109 
110 /* Xtensa GNU/Linux PTRACE interface includes extended register set. */
111 
112 static void
114 {
115  const xtensa_regtable_t *ptr;
116 
117  for (ptr = xtensa_regmap_table; ptr->name; ptr++)
118  {
119  collect_register_by_name (regcache, ptr->name,
120  (char*)buf + ptr->ptrace_offset);
121  }
122 }
123 
124 static void
125 xtensa_store_xtregset (struct regcache *regcache, const void *buf)
126 {
127  const xtensa_regtable_t *ptr;
128 
129  for (ptr = xtensa_regmap_table; ptr->name; ptr++)
130  {
131  supply_register_by_name (regcache, ptr->name,
132  (char*)buf + ptr->ptrace_offset);
133  }
134 }
135 
136 static struct regset_info xtensa_regsets[] = {
137  { PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
138  GENERAL_REGS,
140  { PTRACE_GETXTREGS, PTRACE_SETXTREGS, 0, XTENSA_ELF_XTREG_SIZE,
141  EXTENDED_REGS,
143  { 0, 0, 0, -1, -1, NULL, NULL }
144 };
145 
146 #if XCHAL_HAVE_BE
147 #define XTENSA_BREAKPOINT {0xd2,0x0f}
148 #else
149 #define XTENSA_BREAKPOINT {0x2d,0xf0}
150 #endif
151 
152 static const unsigned char xtensa_breakpoint[] = XTENSA_BREAKPOINT;
153 #define xtensa_breakpoint_len 2
154 
155 static CORE_ADDR
157 {
158  unsigned long pc;
159 
160  collect_register_by_name (regcache, "pc", &pc);
161  return pc;
162 }
163 
164 static void
166 {
167  unsigned long newpc = pc;
168  supply_register_by_name (regcache, "pc", &newpc);
169 }
170 
171 static int
173 {
174  unsigned long insn;
175 
176  (*the_target->read_memory) (where, (unsigned char *) &insn,
178  return memcmp((char *) &insn,
179  xtensa_breakpoint, xtensa_breakpoint_len) == 0;
180 }
181 
182 static struct regsets_info xtensa_regsets_info =
183  {
184  xtensa_regsets, /* regsets */
185  0, /* num_regsets */
186  NULL, /* disabled_regsets */
187  };
188 
189 static struct regs_info regs_info =
190  {
191  NULL, /* regset_bitmap */
192  NULL, /* usrregs */
193  &xtensa_regsets_info
194  };
195 
196 static void
198 {
200 }
201 
202 static const struct regs_info *
204 {
205  return &regs_info;
206 }
207 
208 struct linux_target_ops the_low_target = {
211  0,
212  0,
213  NULL, /* fetch_register */
218  NULL,
219  0,
221 };
222 
223 
224 void
226 {
227  /* Initialize the Linux target descriptions. */
229 
230  initialize_regsets_info (&xtensa_regsets_info);
231 }
const struct target_desc * tdesc
Definition: regcache.h:41
const xtensa_regtable_t xtensa_regmap_table[]
Definition: xtensa-xtregs.c:33
static void xtensa_set_pc(struct regcache *regcache, CORE_ADDR pc)
void collect_register(struct regcache *regcache, int n, void *buf)
Definition: regcache.c:414
bfd_vma CORE_ADDR
Definition: common-types.h:41
void supply_register_by_name(struct regcache *regcache, const char *name, const void *buf)
Definition: regcache.c:405
static struct regs_info regs_info
#define XTENSA_ELF_XTREG_SIZE
Definition: xtensa-xtregs.c:31
static struct regset_info xtensa_regsets[]
static CORE_ADDR xtensa_get_pc(struct regcache *regcache)
regnum
static void xtensa_fill_xtregset(struct regcache *regcache, void *buf)
struct target_ops * the_target
Definition: target.c:24
const struct target_desc * tdesc
Definition: inferiors.h:69
void initialize_low_arch(void)
static const unsigned char xtensa_breakpoint[]
static void xtensa_fill_gregset(struct regcache *regcache, void *buf)
void collect_register_by_name(struct regcache *regcache, const char *name, void *buf)
Definition: regcache.c:430
static void xtensa_arch_setup(void)
static const struct regs_info * xtensa_regs_info(void)
void init_registers_xtensa(void)
static int xtensa_breakpoint_at(CORE_ADDR where)
int register_size(const struct target_desc *tdesc, int n)
Definition: regcache.c:314
const struct target_desc * tdesc_xtensa
struct process_info * current_process(void)
Definition: inferiors.c:356
static void xtensa_store_xtregset(struct regcache *regcache, const void *buf)
#define XTENSA_BREAKPOINT
int find_regno(const struct target_desc *tdesc, const char *name)
Definition: regcache.c:257
#define xtensa_breakpoint_len
int(* read_memory)(CORE_ADDR memaddr, unsigned char *myaddr, int len)
Definition: target.h:160
void supply_register(struct regcache *regcache, int n, const void *buf)
Definition: regcache.c:330
static void xtensa_store_gregset(struct regcache *regcache, const void *buf)