OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.2/] [gdb/] [gdbserver/] [linux-crisv32-low.c] - Blame information for rev 330

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 330 jeremybenn
/* GNU/Linux/CRIS specific low level interface, for the remote server for GDB.
2
   Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3
   2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
 
20
#include "server.h"
21
#include "linux-low.h"
22
#include <sys/ptrace.h>
23
 
24
/* Defined in auto-generated file reg-crisv32.c.  */
25
void init_registers_crisv32 (void);
26
 
27
/* CRISv32 */
28
#define cris_num_regs 49
29
 
30
/* Note: Ignoring USP (having the stack pointer in two locations causes trouble
31
   without any significant gain).  */
32
 
33
/* Locations need to match <include/asm/arch/ptrace.h>.  */
34
static int cris_regmap[] = {
35
  1*4, 2*4, 3*4, 4*4,
36
  5*4, 6*4, 7*4, 8*4,
37
  9*4, 10*4, 11*4, 12*4,
38
  13*4, 14*4, 24*4, 15*4,
39
 
40
  -1, -1, -1, 16*4,
41
  -1, 22*4, 23*4, 17*4,
42
  -1, -1, 21*4, 20*4,
43
  -1, 19*4, -1, 18*4,
44
 
45
  25*4,
46
 
47
  26*4, -1,   -1,   29*4,
48
  30*4, 31*4, 32*4, 33*4,
49
  34*4, 35*4, 36*4, 37*4,
50
  38*4, 39*4, 40*4, -1
51
 
52
};
53
 
54
extern int debug_threads;
55
 
56
static CORE_ADDR
57
cris_get_pc (struct regcache *regcache)
58
{
59
  unsigned long pc;
60
  collect_register_by_name (regcache, "pc", &pc);
61
  if (debug_threads)
62
    fprintf (stderr, "stop pc is %08lx\n", pc);
63
  return pc;
64
}
65
 
66
static void
67
cris_set_pc (struct regcache *regcache, CORE_ADDR pc)
68
{
69
  unsigned long newpc = pc;
70
  supply_register_by_name (regcache, "pc", &newpc);
71
}
72
 
73
static const unsigned short cris_breakpoint = 0xe938;
74
#define cris_breakpoint_len 2
75
 
76
static int
77
cris_breakpoint_at (CORE_ADDR where)
78
{
79
  unsigned short insn;
80
 
81
  (*the_target->read_memory) (where, (unsigned char *) &insn,
82
                              cris_breakpoint_len);
83
  if (insn == cris_breakpoint)
84
    return 1;
85
 
86
  /* If necessary, recognize more trap instructions here.  GDB only uses the
87
     one.  */
88
  return 0;
89
}
90
 
91
/* We only place breakpoints in empty marker functions, and thread locking
92
   is outside of the function.  So rather than importing software single-step,
93
   we can just run until exit.  */
94
 
95
/* FIXME: This function should not be needed, since we have PTRACE_SINGLESTEP
96
   for CRISv32.  Without it, td_ta_event_getmsg in thread_db_create_event
97
   will fail when debugging multi-threaded applications.  */
98
 
99
static CORE_ADDR
100
cris_reinsert_addr (void)
101
{
102
  struct regcache *regcache = get_thread_regcache (current_inferior, 1);
103
  unsigned long pc;
104
  collect_register_by_name (regcache, "srp", &pc);
105
  return pc;
106
}
107
 
108
static void
109
cris_write_data_breakpoint (struct regcache *regcache,
110
                            int bp, unsigned long start, unsigned long end)
111
{
112
  switch (bp)
113
    {
114
    case 0:
115
      supply_register_by_name (regcache, "s3", &start);
116
      supply_register_by_name (regcache, "s4", &end);
117
      break;
118
    case 1:
119
      supply_register_by_name (regcache, "s5", &start);
120
      supply_register_by_name (regcache, "s6", &end);
121
      break;
122
    case 2:
123
      supply_register_by_name (regcache, "s7", &start);
124
      supply_register_by_name (regcache, "s8", &end);
125
      break;
126
    case 3:
127
      supply_register_by_name (regcache, "s9", &start);
128
      supply_register_by_name (regcache, "s10", &end);
129
      break;
130
    case 4:
131
      supply_register_by_name (regcache, "s11", &start);
132
      supply_register_by_name (regcache, "s12", &end);
133
      break;
134
    case 5:
135
      supply_register_by_name (regcache, "s13", &start);
136
      supply_register_by_name (regcache, "s14", &end);
137
      break;
138
    }
139
}
140
 
141
static int
142
cris_insert_point (char type, CORE_ADDR addr, int len)
143
{
144
  int bp;
145
  unsigned long bp_ctrl;
146
  unsigned long start, end;
147
  unsigned long ccs;
148
  struct regcache *regcache;
149
 
150
  /* Breakpoint/watchpoint types (GDB terminology):
151
 
152
     (not supported; done via memory write instead)
153
     1 = hardware breakpoint for instructions (not supported)
154
     2 = write watchpoint (supported)
155
     3 = read watchpoint (supported)
156
     4 = access watchpoint (supported).  */
157
 
158
  if (type < '2' || type > '4')
159
    {
160
      /* Unsupported.  */
161
      return 1;
162
    }
163
 
164
  regcache = get_thread_regcache (current_inferior, 1);
165
 
166
  /* Read watchpoints are set as access watchpoints, because of GDB's
167
     inability to deal with pure read watchpoints.  */
168
  if (type == '3')
169
    type = '4';
170
 
171
  /* Get the configuration register.  */
172
  collect_register_by_name (regcache, "s0", &bp_ctrl);
173
 
174
  /* The watchpoint allocation scheme is the simplest possible.
175
     For example, if a region is watched for read and
176
     a write watch is requested, a new watchpoint will
177
     be used.  Also, if a watch for a region that is already
178
     covered by one or more existing watchpoints, a new
179
     watchpoint will be used.  */
180
 
181
  /* First, find a free data watchpoint.  */
182
  for (bp = 0; bp < 6; bp++)
183
    {
184
      /* Each data watchpoint's control registers occupy 2 bits
185
         (hence the 3), starting at bit 2 for D0 (hence the 2)
186
         with 4 bits between for each watchpoint (yes, the 4).  */
187
      if (!(bp_ctrl & (0x3 << (2 + (bp * 4)))))
188
        break;
189
    }
190
 
191
  if (bp > 5)
192
    {
193
      /* We're out of watchpoints.  */
194
      return -1;
195
    }
196
 
197
  /* Configure the control register first.  */
198
  if (type == '3' || type == '4')
199
    {
200
      /* Trigger on read.  */
201
      bp_ctrl |= (1 << (2 + bp * 4));
202
    }
203
  if (type == '2' || type == '4')
204
    {
205
      /* Trigger on write.  */
206
      bp_ctrl |= (2 << (2 + bp * 4));
207
    }
208
 
209
  /* Setup the configuration register.  */
210
  supply_register_by_name (regcache, "s0", &bp_ctrl);
211
 
212
  /* Setup the range.  */
213
  start = addr;
214
  end = addr + len - 1;
215
 
216
  /* Configure the watchpoint register.  */
217
  cris_write_data_breakpoint (regcache, bp, start, end);
218
 
219
  collect_register_by_name (regcache, "ccs", &ccs);
220
  /* Set the S1 flag to enable watchpoints.  */
221
  ccs |= (1 << 19);
222
  supply_register_by_name (regcache, "ccs", &ccs);
223
 
224
  return 0;
225
}
226
 
227
static int
228
cris_remove_point (char type, CORE_ADDR addr, int len)
229
{
230
  int bp;
231
  unsigned long bp_ctrl;
232
  unsigned long start, end;
233
  struct regcache *regcache;
234
 
235
  /* Breakpoint/watchpoint types:
236
 
237
     (not supported; done via memory write instead)
238
     1 = hardware breakpoint for instructions (not supported)
239
     2 = write watchpoint (supported)
240
     3 = read watchpoint (supported)
241
     4 = access watchpoint (supported).  */
242
  if (type < '2' || type > '4')
243
    return -1;
244
 
245
  regcache = get_thread_regcache (current_inferior, 1);
246
 
247
  /* Read watchpoints are set as access watchpoints, because of GDB's
248
     inability to deal with pure read watchpoints.  */
249
  if (type == '3')
250
    type = '4';
251
 
252
  /* Get the configuration register.  */
253
  collect_register_by_name (regcache, "s0", &bp_ctrl);
254
 
255
  /* Try to find a watchpoint that is configured for the
256
     specified range, then check that read/write also matches.  */
257
 
258
  /* Ugly pointer arithmetic, since I cannot rely on a
259
     single switch (addr) as there may be several watchpoints with
260
     the same start address for example.  */
261
 
262
  unsigned long bp_d_regs[12];
263
 
264
  /* Get all range registers to simplify search.  */
265
  collect_register_by_name (regcache, "s3", &bp_d_regs[0]);
266
  collect_register_by_name (regcache, "s4", &bp_d_regs[1]);
267
  collect_register_by_name (regcache, "s5", &bp_d_regs[2]);
268
  collect_register_by_name (regcache, "s6", &bp_d_regs[3]);
269
  collect_register_by_name (regcache, "s7", &bp_d_regs[4]);
270
  collect_register_by_name (regcache, "s8", &bp_d_regs[5]);
271
  collect_register_by_name (regcache, "s9", &bp_d_regs[6]);
272
  collect_register_by_name (regcache, "s10", &bp_d_regs[7]);
273
  collect_register_by_name (regcache, "s11", &bp_d_regs[8]);
274
  collect_register_by_name (regcache, "s12", &bp_d_regs[9]);
275
  collect_register_by_name (regcache, "s13", &bp_d_regs[10]);
276
  collect_register_by_name (regcache, "s14", &bp_d_regs[11]);
277
 
278
  for (bp = 0; bp < 6; bp++)
279
    {
280
      if (bp_d_regs[bp * 2] == addr
281
          && bp_d_regs[bp * 2 + 1] == (addr + len - 1)) {
282
        /* Matching range.  */
283
        int bitpos = 2 + bp * 4;
284
        int rw_bits;
285
 
286
        /* Read/write bits for this BP.  */
287
        rw_bits = (bp_ctrl & (0x3 << bitpos)) >> bitpos;
288
 
289
        if ((type == '3' && rw_bits == 0x1)
290
            || (type == '2' && rw_bits == 0x2)
291
            || (type == '4' && rw_bits == 0x3))
292
          {
293
            /* Read/write matched.  */
294
            break;
295
          }
296
      }
297
    }
298
 
299
  if (bp > 5)
300
    {
301
      /* No watchpoint matched.  */
302
      return -1;
303
    }
304
 
305
  /* Found a matching watchpoint.  Now, deconfigure it by
306
     both disabling read/write in bp_ctrl and zeroing its
307
     start/end addresses.  */
308
  bp_ctrl &= ~(3 << (2 + (bp * 4)));
309
  /* Setup the configuration register.  */
310
  supply_register_by_name (regcache, "s0", &bp_ctrl);
311
 
312
  start = end = 0;
313
  /* Configure the watchpoint register.  */
314
  cris_write_data_breakpoint (regcache, bp, start, end);
315
 
316
  /* Note that we don't clear the S1 flag here.  It's done when continuing.  */
317
  return 0;
318
}
319
 
320
static int
321
cris_stopped_by_watchpoint (void)
322
{
323
  unsigned long exs;
324
 
325
  collect_register_by_name ("exs", &exs);
326
 
327
  return (((exs & 0xff00) >> 8) == 0xc);
328
}
329
 
330
static CORE_ADDR
331
cris_stopped_data_address (void)
332
{
333
  unsigned long eda;
334
 
335
  collect_register_by_name ("eda", &eda);
336
 
337
  /* FIXME: Possibly adjust to match watched range.  */
338
  return eda;
339
}
340
 
341
static void
342
cris_fill_gregset (void *buf)
343
{
344
  int i;
345
 
346
  for (i = 0; i < cris_num_regs; i++)
347
    {
348
      if (cris_regmap[i] != -1)
349
        collect_register (i, ((char *) buf) + cris_regmap[i]);
350
    }
351
}
352
 
353
static void
354
cris_store_gregset (const void *buf)
355
{
356
  int i;
357
 
358
  for (i = 0; i < cris_num_regs; i++)
359
    {
360
      if (cris_regmap[i] != -1)
361
        supply_register (i, ((char *) buf) + cris_regmap[i]);
362
    }
363
}
364
 
365
typedef unsigned long elf_gregset_t[cris_num_regs];
366
 
367
struct regset_info target_regsets[] = {
368
  { PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
369
    GENERAL_REGS, cris_fill_gregset, cris_store_gregset },
370
  { 0, 0, 0, -1, -1, NULL, NULL }
371
};
372
 
373
struct linux_target_ops the_low_target = {
374
  init_register_crisv32,
375
  -1,
376
  NULL,
377
  NULL,
378
  NULL,
379
  cris_get_pc,
380
  cris_set_pc,
381
  (const unsigned char *) &cris_breakpoint,
382
  cris_breakpoint_len,
383
  cris_reinsert_addr,
384
  0,
385
  cris_breakpoint_at,
386
  cris_insert_point,
387
  cris_remove_point,
388
  cris_stopped_by_watchpoint,
389
  cris_stopped_data_address,
390
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.