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