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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [memattr.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Memory attributes support, for GDB.
2
   Copyright 2001 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 2 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, write to the Free Software
18
   Foundation, Inc., 59 Temple Place - Suite 330,
19
   Boston, MA 02111-1307, USA.  */
20
 
21
#include "defs.h"
22
#include "command.h"
23
#include "gdbcmd.h"
24
#include "memattr.h"
25
#include "target.h"
26
#include "value.h"
27
#include "language.h"
28
#include "gdb_string.h"
29
 
30
/* FIXME: While this conflicts with the enum defined in breakpoint.h,
31
   I used them to be consistant with how breakpoints, tracepoints, and
32
   displays are implemented.  It doesn't lose now because breakpoint.h
33
   is not included.  */
34
enum enable
35
{
36
  disabled,
37
  enabled
38
};
39
 
40
const struct mem_attrib default_mem_attrib =
41
{
42
  MEM_RW,                       /* mode */
43
  MEM_WIDTH_UNSPECIFIED,
44
  false,                        /* hwbreak */
45
  false,                        /* cache */
46
  false                         /* verify */
47
};
48
 
49
static struct mem_region *mem_region_chain = NULL;
50
static int mem_number = 0;
51
 
52
static struct mem_region *
53
create_mem_region (CORE_ADDR lo, CORE_ADDR hi,
54
                   const struct mem_attrib *attrib)
55
{
56
  struct mem_region *n, *new;
57
 
58
  if (lo > hi)
59
    {
60
      printf_unfiltered ("invalid memory region\n");
61
      return NULL;
62
    }
63
 
64
  n = mem_region_chain;
65
  while (n)
66
    {
67
      /* overlapping node */
68
      if ((lo >= n->lo && lo <= n->hi) ||
69
          (hi >= n->lo && hi <= n->hi))
70
        {
71
          printf_unfiltered ("overlapping memory region\n");
72
          return NULL;
73
        }
74
      n = n->next;
75
    }
76
 
77
  new = xmalloc (sizeof (struct mem_region));
78
  new->lo = lo;
79
  new->hi = hi;
80
  new->number = ++mem_number;
81
  new->status = enabled;
82
  new->attrib = *attrib;
83
 
84
  /* link in new node */
85
  new->next = mem_region_chain;
86
  mem_region_chain = new;
87
 
88
  return new;
89
}
90
 
91
static void
92
delete_mem_region (struct mem_region *m)
93
{
94
  xfree (m);
95
}
96
 
97
/*
98
 * Look up the memory region cooresponding to ADDR.
99
 */
100
struct mem_region *
101
lookup_mem_region (CORE_ADDR addr)
102
{
103
  static struct mem_region region;
104
  struct mem_region *m;
105
  CORE_ADDR lo;
106
  CORE_ADDR hi;
107
 
108
  /* First we initialize LO and HI so that they describe the entire
109
     memory space.  As we process the memory region chain, they are
110
     redefined to describe the minimal region containing ADDR.  LO
111
     and HI are used in the case where no memory region is defined
112
     that contains ADDR.  If a memory region is disabled, it is
113
     treated as if it does not exist.  */
114
 
115
  lo = (CORE_ADDR) 0;
116
  hi = (CORE_ADDR) ~ 0;
117
 
118
  for (m = mem_region_chain; m; m = m->next)
119
    {
120
      if (m->status == enabled)
121
        {
122
          if (addr >= m->lo && addr < m->hi)
123
            return m;
124
 
125
          if (addr >= m->hi && lo < m->hi)
126
            lo = m->hi;
127
 
128
          if (addr <= m->lo && hi > m->lo)
129
            hi = m->lo;
130
        }
131
    }
132
 
133
  /* Because no region was found, we must cons up one based on what
134
     was learned above.  */
135
  region.lo = lo;
136
  region.hi = hi;
137
  region.attrib = default_mem_attrib;
138
  return &region;
139
}
140
 
141
 
142
static void
143
mem_command (char *args, int from_tty)
144
{
145
  CORE_ADDR lo, hi;
146
  char *tok;
147
  struct mem_attrib attrib;
148
 
149
  if (!args)
150
    error_no_arg ("No mem");
151
 
152
  tok = strtok (args, " \t");
153
  if (!tok)
154
    error ("no lo address");
155
  lo = parse_and_eval_address (tok);
156
 
157
  tok = strtok (NULL, " \t");
158
  if (!tok)
159
    error ("no hi address");
160
  hi = parse_and_eval_address (tok);
161
 
162
  attrib = default_mem_attrib;
163
  while ((tok = strtok (NULL, " \t")) != NULL)
164
    {
165
      if (strcmp (tok, "rw") == 0)
166
        attrib.mode = MEM_RW;
167
      else if (strcmp (tok, "ro") == 0)
168
        attrib.mode = MEM_RO;
169
      else if (strcmp (tok, "wo") == 0)
170
        attrib.mode = MEM_WO;
171
 
172
      else if (strcmp (tok, "8") == 0)
173
        attrib.width = MEM_WIDTH_8;
174
      else if (strcmp (tok, "16") == 0)
175
        {
176
          if ((lo % 2 != 0) || (hi % 2 != 0))
177
            error ("region bounds not 16 bit aligned");
178
          attrib.width = MEM_WIDTH_16;
179
        }
180
      else if (strcmp (tok, "32") == 0)
181
        {
182
          if ((lo % 4 != 0) || (hi % 4 != 0))
183
            error ("region bounds not 32 bit aligned");
184
          attrib.width = MEM_WIDTH_32;
185
        }
186
      else if (strcmp (tok, "64") == 0)
187
        {
188
          if ((lo % 8 != 0) || (hi % 8 != 0))
189
            error ("region bounds not 64 bit aligned");
190
          attrib.width = MEM_WIDTH_64;
191
        }
192
 
193
#if 0
194
      else if (strcmp (tok, "hwbreak") == 0)
195
        attrib.hwbreak = true;
196
      else if (strcmp (tok, "swbreak") == 0)
197
        attrib.hwbreak = false;
198
#endif
199
 
200
      else if (strcmp (tok, "cache") == 0)
201
        attrib.cache = true;
202
      else if (strcmp (tok, "nocache") == 0)
203
        attrib.cache = false;
204
 
205
#if 0
206
      else if (strcmp (tok, "verify") == 0)
207
        attrib.verify = true;
208
      else if (strcmp (tok, "noverify") == 0)
209
        attrib.verify = false;
210
#endif
211
 
212
      else
213
        error ("unknown attribute: %s", tok);
214
    }
215
 
216
  create_mem_region (lo, hi, &attrib);
217
}
218
 
219
 
220
static void
221
mem_info_command (char *args, int from_tty)
222
{
223
  struct mem_region *m;
224
  struct mem_attrib *attrib;
225
 
226
  if (!mem_region_chain)
227
    {
228
      printf_unfiltered ("There are no memory regions defined.\n");
229
      return;
230
    }
231
 
232
  printf_filtered ("Memory regions now in effect:\n");
233
  for (m = mem_region_chain; m; m = m->next)
234
    {
235
      printf_filtered ("%d: %c\t",
236
                       m->number,
237
                       m->status ? 'y' : 'n');
238
      printf_filtered ("%s - ",
239
                    local_hex_string_custom ((unsigned long) m->lo, "08l"));
240
      printf_filtered ("%s\t",
241
                    local_hex_string_custom ((unsigned long) m->hi, "08l"));
242
 
243
      /* Print a token for each attribute.
244
 
245
       * FIXME: Should we output a comma after each token?  It may
246
       * make it easier for users to read, but we'd lose the ability
247
       * to cut-and-paste the list of attributes when defining a new
248
       * region.  Perhaps that is not important.
249
       *
250
       * FIXME: If more attributes are added to GDB, the output may
251
       * become cluttered and difficult for users to read.  At that
252
       * time, we may want to consider printing tokens only if they
253
       * are different from the default attribute.  */
254
 
255
      attrib = &m->attrib;
256
      switch (attrib->mode)
257
        {
258
        case MEM_RW:
259
          printf_filtered ("rw ");
260
          break;
261
        case MEM_RO:
262
          printf_filtered ("ro ");
263
          break;
264
        case MEM_WO:
265
          printf_filtered ("wo ");
266
          break;
267
        }
268
 
269
      switch (attrib->width)
270
        {
271
        case MEM_WIDTH_8:
272
          printf_filtered ("8 ");
273
          break;
274
        case MEM_WIDTH_16:
275
          printf_filtered ("16 ");
276
          break;
277
        case MEM_WIDTH_32:
278
          printf_filtered ("32 ");
279
          break;
280
        case MEM_WIDTH_64:
281
          printf_filtered ("64 ");
282
          break;
283
        case MEM_WIDTH_UNSPECIFIED:
284
          break;
285
        }
286
 
287
#if 0
288
      if (attrib->hwbreak)
289
        printf_filtered ("hwbreak");
290
      else
291
        printf_filtered ("swbreak");
292
#endif
293
 
294
      if (attrib->cache)
295
        printf_filtered ("cache ");
296
      else
297
        printf_filtered ("nocache ");
298
 
299
#if 0
300
      if (attrib->verify)
301
        printf_filtered ("verify ");
302
      else
303
        printf_filtered ("noverify ");
304
#endif
305
 
306
      printf_filtered ("\n");
307
 
308
      gdb_flush (gdb_stdout);
309
    }
310
}
311
 
312
 
313
/* Enable the memory region number NUM. */
314
 
315
static void
316
mem_enable (int num)
317
{
318
  struct mem_region *m;
319
 
320
  for (m = mem_region_chain; m; m = m->next)
321
    if (m->number == num)
322
      {
323
        m->status = enabled;
324
        return;
325
      }
326
  printf_unfiltered ("No memory region number %d.\n", num);
327
}
328
 
329
static void
330
mem_enable_command (char *args, int from_tty)
331
{
332
  char *p = args;
333
  char *p1;
334
  int num;
335
  struct mem_region *m;
336
 
337
  dcache_invalidate (target_dcache);
338
 
339
  if (p == 0)
340
    {
341
      for (m = mem_region_chain; m; m = m->next)
342
        m->status = enabled;
343
    }
344
  else
345
    while (*p)
346
      {
347
        p1 = p;
348
        while (*p1 >= '0' && *p1 <= '9')
349
          p1++;
350
        if (*p1 && *p1 != ' ' && *p1 != '\t')
351
          error ("Arguments must be memory region numbers.");
352
 
353
        num = atoi (p);
354
        mem_enable (num);
355
 
356
        p = p1;
357
        while (*p == ' ' || *p == '\t')
358
          p++;
359
      }
360
}
361
 
362
 
363
/* Disable the memory region number NUM. */
364
 
365
static void
366
mem_disable (int num)
367
{
368
  struct mem_region *m;
369
 
370
  for (m = mem_region_chain; m; m = m->next)
371
    if (m->number == num)
372
      {
373
        m->status = disabled;
374
        return;
375
      }
376
  printf_unfiltered ("No memory region number %d.\n", num);
377
}
378
 
379
static void
380
mem_disable_command (char *args, int from_tty)
381
{
382
  char *p = args;
383
  char *p1;
384
  int num;
385
  struct mem_region *m;
386
 
387
  dcache_invalidate (target_dcache);
388
 
389
  if (p == 0)
390
    {
391
      for (m = mem_region_chain; m; m = m->next)
392
        m->status = disabled;
393
    }
394
  else
395
    while (*p)
396
      {
397
        p1 = p;
398
        while (*p1 >= '0' && *p1 <= '9')
399
          p1++;
400
        if (*p1 && *p1 != ' ' && *p1 != '\t')
401
          error ("Arguments must be memory region numbers.");
402
 
403
        num = atoi (p);
404
        mem_disable (num);
405
 
406
        p = p1;
407
        while (*p == ' ' || *p == '\t')
408
          p++;
409
      }
410
}
411
 
412
/* Clear memory region list */
413
 
414
static void
415
mem_clear (void)
416
{
417
  struct mem_region *m;
418
 
419
  while ((m = mem_region_chain) != 0)
420
    {
421
      mem_region_chain = m->next;
422
      delete_mem_region (m);
423
    }
424
}
425
 
426
/* Delete the memory region number NUM. */
427
 
428
static void
429
mem_delete (int num)
430
{
431
  struct mem_region *m1, *m;
432
 
433
  if (!mem_region_chain)
434
    {
435
      printf_unfiltered ("No memory region number %d.\n", num);
436
      return;
437
    }
438
 
439
  if (mem_region_chain->number == num)
440
    {
441
      m1 = mem_region_chain;
442
      mem_region_chain = m1->next;
443
      delete_mem_region (m1);
444
    }
445
  else
446
    for (m = mem_region_chain; m->next; m = m->next)
447
      {
448
        if (m->next->number == num)
449
          {
450
            m1 = m->next;
451
            m->next = m1->next;
452
            delete_mem_region (m1);
453
            break;
454
          }
455
      }
456
}
457
 
458
static void
459
mem_delete_command (char *args, int from_tty)
460
{
461
  char *p = args;
462
  char *p1;
463
  int num;
464
 
465
  dcache_invalidate (target_dcache);
466
 
467
  if (p == 0)
468
    {
469
      if (query ("Delete all memory regions? "))
470
        mem_clear ();
471
      dont_repeat ();
472
      return;
473
    }
474
 
475
  while (*p)
476
    {
477
      p1 = p;
478
      while (*p1 >= '0' && *p1 <= '9')
479
        p1++;
480
      if (*p1 && *p1 != ' ' && *p1 != '\t')
481
        error ("Arguments must be memory region numbers.");
482
 
483
      num = atoi (p);
484
      mem_delete (num);
485
 
486
      p = p1;
487
      while (*p == ' ' || *p == '\t')
488
        p++;
489
    }
490
 
491
  dont_repeat ();
492
}
493
 
494
void
495
_initialize_mem ()
496
{
497
  add_com ("mem", class_vars, mem_command,
498
           "Define attributes for memory region.");
499
 
500
  add_cmd ("mem", class_vars, mem_enable_command,
501
           "Enable memory region.\n\
502
Arguments are the code numbers of the memory regions to enable.\n\
503
Do \"info mem\" to see current list of code numbers.", &enablelist);
504
 
505
  add_cmd ("mem", class_vars, mem_disable_command,
506
           "Disable memory region.\n\
507
Arguments are the code numbers of the memory regions to disable.\n\
508
Do \"info mem\" to see current list of code numbers.", &disablelist);
509
 
510
  add_cmd ("mem", class_vars, mem_delete_command,
511
           "Delete memory region.\n\
512
Arguments are the code numbers of the memory regions to delete.\n\
513
Do \"info mem\" to see current list of code numbers.", &deletelist);
514
 
515
  add_info ("mem", mem_info_command,
516
            "Memory region attributes");
517
}

powered by: WebSVN 2.1.0

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