Commit | Line | Data |
---|---|---|
a34abff8 AC |
1 | /* Simulator memory option handling. |
2 | Copyright (C) 1996, 1997 Free Software Foundation, Inc. | |
3 | Contributed by Cygnus Support. | |
4 | ||
5 | This file is part of GDB, the GNU debugger. | |
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 2, or (at your option) | |
10 | 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 along | |
18 | with this program; if not, write to the Free Software Foundation, Inc., | |
19 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
20 | ||
21 | #include "sim-main.h" | |
22 | #include "sim-assert.h" | |
23 | #include "sim-options.h" | |
24 | ||
25 | #ifdef HAVE_STRING_H | |
26 | #include <string.h> | |
27 | #else | |
28 | #ifdef HAVE_STRINGS_H | |
29 | #include <strings.h> | |
30 | #endif | |
31 | #endif | |
32 | #ifdef HAVE_STDLIB_H | |
33 | #include <stdlib.h> | |
34 | #endif | |
35 | ||
36 | /* "core" command line options. */ | |
37 | ||
38 | enum { | |
39 | OPTION_MEMORY_DELETE = OPTION_START, | |
40 | OPTION_MEMORY_REGION, | |
41 | OPTION_MEMORY_SIZE, | |
42 | OPTION_MEMORY_INFO, | |
43 | OPTION_MEMORY_ALIAS, | |
44 | OPTION_MEMORY_CLEAR, | |
45 | }; | |
46 | ||
47 | static DECLARE_OPTION_HANDLER (memory_option_handler); | |
48 | ||
49 | static const OPTION memory_options[] = | |
50 | { | |
fcc86d82 AC |
51 | { {"memory-delete", required_argument, NULL, OPTION_MEMORY_DELETE }, |
52 | '\0', "ADDRESS|all", "Delete memory at ADDRESS (all addresses)", | |
6dbaff8f | 53 | memory_option_handler }, |
a34abff8 | 54 | { {"delete-memory", required_argument, NULL, OPTION_MEMORY_DELETE }, |
6dbaff8f | 55 | '\0', "ADDRESS", NULL, |
a34abff8 AC |
56 | memory_option_handler }, |
57 | ||
58 | { {"memory-region", required_argument, NULL, OPTION_MEMORY_REGION }, | |
59 | '\0', "ADDRESS,SIZE[,MODULO]", "Add a memory region", | |
60 | memory_option_handler }, | |
61 | ||
62 | { {"memory-alias", required_argument, NULL, OPTION_MEMORY_ALIAS }, | |
63 | '\0', "ADDRESS,SIZE{,ADDRESS}", "Add memory shadow", | |
64 | memory_option_handler }, | |
65 | ||
66 | { {"memory-size", required_argument, NULL, OPTION_MEMORY_SIZE }, | |
67 | '\0', "SIZE", "Add memory at address zero", | |
68 | memory_option_handler }, | |
69 | ||
70 | { {"memory-clear", no_argument, NULL, OPTION_MEMORY_CLEAR }, | |
71 | '\0', NULL, "Clear all memory regions", | |
72 | memory_option_handler }, | |
73 | ||
6dbaff8f AC |
74 | { {"memory-info", no_argument, NULL, OPTION_MEMORY_INFO }, |
75 | '\0', NULL, "List configurable memory regions", | |
76 | memory_option_handler }, | |
a34abff8 | 77 | { {"info-memory", no_argument, NULL, OPTION_MEMORY_INFO }, |
6dbaff8f | 78 | '\0', NULL, NULL, |
a34abff8 AC |
79 | memory_option_handler }, |
80 | ||
81 | { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } | |
82 | }; | |
83 | ||
84 | ||
6dbaff8f | 85 | static sim_memopt * |
fcc86d82 AC |
86 | do_memopt_add (SIM_DESC sd, |
87 | int level, | |
88 | int space, | |
89 | address_word addr, | |
90 | address_word nr_bytes, | |
91 | unsigned modulo, | |
92 | sim_memopt **entry, | |
93 | void *buffer) | |
6dbaff8f AC |
94 | { |
95 | sim_core_attach (sd, NULL, | |
fcc86d82 | 96 | level, access_read_write_exec, space, |
6dbaff8f AC |
97 | addr, nr_bytes, modulo, NULL, buffer); |
98 | while ((*entry) != NULL) | |
99 | entry = &(*entry)->next; | |
100 | (*entry) = ZALLOC (sim_memopt); | |
fcc86d82 AC |
101 | (*entry)->level = level; |
102 | (*entry)->space = space; | |
6dbaff8f AC |
103 | (*entry)->addr = addr; |
104 | (*entry)->nr_bytes = nr_bytes; | |
105 | (*entry)->modulo = modulo; | |
106 | (*entry)->buffer = buffer; | |
107 | return (*entry); | |
108 | } | |
109 | ||
110 | static SIM_RC | |
fcc86d82 AC |
111 | do_memopt_delete (SIM_DESC sd, |
112 | int level, | |
113 | int space, | |
114 | address_word addr) | |
6dbaff8f AC |
115 | { |
116 | sim_memopt **entry = &STATE_MEMOPT (sd); | |
117 | sim_memopt *alias; | |
fcc86d82 AC |
118 | while ((*entry) != NULL |
119 | && ((*entry)->level != level | |
120 | || (*entry)->space != space | |
121 | || (*entry)->addr != addr)) | |
6dbaff8f AC |
122 | entry = &(*entry)->next; |
123 | if ((*entry) == NULL) | |
124 | { | |
125 | sim_io_eprintf (sd, "Memory at 0x%lx not found, not deleted\n", | |
126 | (long) addr); | |
127 | return SIM_RC_FAIL; | |
128 | } | |
129 | /* delete any buffer */ | |
130 | if ((*entry)->buffer != NULL) | |
131 | zfree ((*entry)->buffer); | |
132 | /* delete it and its aliases */ | |
133 | alias = *entry; | |
fcc86d82 | 134 | *entry = (*entry)->next; |
6dbaff8f AC |
135 | while (alias != NULL) |
136 | { | |
137 | sim_memopt *dead = alias; | |
138 | alias = alias->alias; | |
fcc86d82 | 139 | sim_core_detach (sd, NULL, dead->level, dead->space, dead->addr); |
6dbaff8f AC |
140 | zfree (dead); |
141 | } | |
142 | return SIM_RC_OK; | |
143 | } | |
144 | ||
145 | ||
fcc86d82 AC |
146 | static char * |
147 | parse_size (char *chp, | |
148 | address_word *nr_bytes, | |
149 | unsigned *modulo) | |
150 | { | |
151 | /* <nr_bytes> [ "%" <modulo> ] */ | |
152 | *nr_bytes = strtoul (chp, &chp, 0); | |
153 | if (*chp == '%') | |
154 | { | |
155 | *modulo = strtoul (chp + 1, &chp, 0); | |
156 | } | |
157 | return chp; | |
158 | } | |
159 | ||
160 | ||
161 | static char * | |
162 | parse_addr (char *chp, | |
163 | int *level, | |
164 | int *space, | |
165 | address_word *addr) | |
166 | { | |
167 | /* [ <space> ": " ] <addr> [ "@" <level> ] */ | |
168 | *addr = strtoul (chp, &chp, 0); | |
169 | if (*chp == ':') | |
170 | { | |
171 | *space = *addr; | |
172 | *addr = strtoul (chp + 1, &chp, 0); | |
173 | } | |
174 | if (*chp == '@') | |
175 | { | |
176 | *level = strtoul (chp + 1, &chp, 0); | |
177 | } | |
178 | return chp; | |
179 | } | |
180 | ||
181 | ||
a34abff8 AC |
182 | static SIM_RC |
183 | memory_option_handler (sd, opt, arg, is_command) | |
184 | SIM_DESC sd; | |
185 | int opt; | |
186 | char *arg; | |
187 | int is_command; | |
188 | { | |
189 | switch (opt) | |
190 | { | |
191 | ||
192 | case OPTION_MEMORY_DELETE: | |
fcc86d82 | 193 | if (strcasecmp (arg, "all") == 0) |
6dbaff8f AC |
194 | { |
195 | while (STATE_MEMOPT (sd) != NULL) | |
fcc86d82 AC |
196 | do_memopt_delete (sd, |
197 | STATE_MEMOPT (sd)->level, | |
198 | STATE_MEMOPT (sd)->space, | |
199 | STATE_MEMOPT (sd)->addr); | |
6dbaff8f AC |
200 | return SIM_RC_OK; |
201 | } | |
202 | else | |
203 | { | |
fcc86d82 AC |
204 | int level = 0; |
205 | int space = 0; | |
206 | address_word addr = 0; | |
207 | parse_addr (arg, &level, &space, &addr); | |
208 | return do_memopt_delete (sd, level, space, addr); | |
6dbaff8f | 209 | } |
a34abff8 AC |
210 | |
211 | case OPTION_MEMORY_REGION: | |
212 | { | |
213 | char *chp = arg; | |
fcc86d82 AC |
214 | int level = 0; |
215 | int space = 0; | |
a34abff8 AC |
216 | address_word addr = 0; |
217 | address_word nr_bytes = 0; | |
218 | unsigned modulo = 0; | |
a34abff8 | 219 | /* parse the arguments */ |
fcc86d82 | 220 | chp = parse_addr (chp, &level, &space, &addr); |
a34abff8 AC |
221 | if (*chp != ',') |
222 | { | |
223 | sim_io_eprintf (sd, "Missing size for memory-region\n"); | |
224 | return SIM_RC_FAIL; | |
225 | } | |
fcc86d82 AC |
226 | chp = parse_size (chp + 1, &nr_bytes, &modulo); |
227 | /* old style */ | |
a34abff8 | 228 | if (*chp == ',') |
fcc86d82 | 229 | modulo = strtoul (chp + 1, &chp, 0); |
6dbaff8f | 230 | /* try to attach/insert it */ |
fcc86d82 AC |
231 | do_memopt_add (sd, level, space, addr, nr_bytes, modulo, |
232 | &STATE_MEMOPT (sd), NULL); | |
a34abff8 AC |
233 | return SIM_RC_OK; |
234 | } | |
235 | ||
236 | case OPTION_MEMORY_ALIAS: | |
237 | { | |
6dbaff8f | 238 | char *chp = arg; |
fcc86d82 AC |
239 | int level = 0; |
240 | int space = 0; | |
6dbaff8f AC |
241 | address_word addr = 0; |
242 | address_word nr_bytes = 0; | |
fcc86d82 | 243 | unsigned modulo = 0; |
6dbaff8f AC |
244 | sim_memopt *entry; |
245 | /* parse the arguments */ | |
fcc86d82 | 246 | chp = parse_addr (chp, &level, &space, &addr); |
6dbaff8f AC |
247 | if (*chp != ',') |
248 | { | |
249 | sim_io_eprintf (sd, "Missing size for memory-region\n"); | |
250 | return SIM_RC_FAIL; | |
251 | } | |
fcc86d82 | 252 | chp = parse_size (chp + 1, &nr_bytes, &modulo); |
6dbaff8f | 253 | /* try to attach/insert the main record */ |
fcc86d82 | 254 | entry = do_memopt_add (sd, level, space, addr, nr_bytes, modulo, |
6dbaff8f AC |
255 | &STATE_MEMOPT (sd), zalloc (nr_bytes)); |
256 | /* now attach all the aliases */ | |
257 | while (*chp == ',') | |
258 | { | |
fcc86d82 AC |
259 | int a_level = level; |
260 | int a_space = space; | |
261 | address_word a_addr = addr; | |
262 | chp = parse_addr (chp, &a_level, &a_space, &a_addr); | |
263 | do_memopt_add (sd, a_level, a_space, a_addr, nr_bytes, modulo, | |
6dbaff8f AC |
264 | &entry->alias, entry->buffer); |
265 | } | |
266 | return SIM_RC_OK; | |
a34abff8 AC |
267 | } |
268 | ||
269 | case OPTION_MEMORY_SIZE: | |
270 | { | |
fcc86d82 AC |
271 | int level = 0; |
272 | int space = 0; | |
273 | address_word addr = 0; | |
274 | address_word nr_bytes = 0; | |
275 | unsigned modulo = 0; | |
276 | /* parse the arguments */ | |
277 | parse_size (arg, &nr_bytes, &modulo); | |
6dbaff8f | 278 | /* try to attach/insert it */ |
fcc86d82 | 279 | do_memopt_add (sd, level, space, addr, nr_bytes, modulo, |
6dbaff8f AC |
280 | &STATE_MEMOPT (sd), NULL); |
281 | return SIM_RC_OK; | |
a34abff8 AC |
282 | } |
283 | ||
284 | case OPTION_MEMORY_CLEAR: | |
285 | { | |
286 | sim_memopt *entry; | |
287 | for (entry = STATE_MEMOPT (sd); entry != NULL; entry = entry->next) | |
288 | { | |
289 | sim_memopt *alias; | |
290 | for (alias = entry; alias != NULL; alias = alias->next) | |
291 | { | |
292 | unsigned8 zero = 0; | |
293 | address_word nr_bytes; | |
294 | if (alias->modulo != 0) | |
295 | nr_bytes = alias->modulo; | |
296 | else | |
297 | nr_bytes = alias->nr_bytes; | |
298 | sim_core_write_buffer (sd, NULL, sim_core_write_map, | |
299 | &zero, | |
300 | alias->addr + nr_bytes, | |
301 | sizeof (zero)); | |
302 | ||
303 | } | |
304 | } | |
305 | return SIM_RC_OK; | |
306 | break; | |
307 | } | |
308 | ||
309 | case OPTION_MEMORY_INFO: | |
310 | { | |
311 | sim_memopt *entry; | |
312 | sim_io_printf (sd, "Memory maps:\n"); | |
313 | for (entry = STATE_MEMOPT (sd); entry != NULL; entry = entry->next) | |
314 | { | |
315 | sim_memopt *alias; | |
316 | sim_io_printf (sd, " memory"); | |
317 | if (entry->alias == NULL) | |
fcc86d82 | 318 | sim_io_printf (sd, " region "); |
a34abff8 | 319 | else |
fcc86d82 AC |
320 | sim_io_printf (sd, " alias "); |
321 | if (entry->space != 0) | |
322 | sim_io_printf (sd, "0x%lx:", (long) entry->space); | |
323 | sim_io_printf (sd, "0x%08lx", | |
324 | (long) entry->addr); | |
325 | if (entry->level != 0) | |
326 | sim_io_printf (sd, "@0x%lx", (long) entry->level); | |
327 | sim_io_printf (sd, ",0x%lx", | |
328 | (long) entry->nr_bytes); | |
329 | if (entry->modulo != 0) | |
330 | sim_io_printf (sd, "%%0x%lx", (long) entry->modulo); | |
331 | for (alias = entry->alias; | |
332 | alias != NULL; | |
333 | alias = alias->next) | |
a34abff8 | 334 | { |
fcc86d82 AC |
335 | if (alias->space != 0) |
336 | sim_io_printf (sd, "0x%lx:", (long) alias->space); | |
337 | sim_io_printf (sd, ",0x%08lx", alias->addr); | |
338 | if (alias->level != 0) | |
339 | sim_io_printf (sd, "@0x%lx", (long) alias->level); | |
a34abff8 AC |
340 | } |
341 | sim_io_printf (sd, "\n"); | |
342 | } | |
343 | return SIM_RC_OK; | |
344 | break; | |
345 | } | |
346 | ||
347 | default: | |
348 | sim_io_eprintf (sd, "Unknown watch option %d\n", opt); | |
349 | return SIM_RC_FAIL; | |
350 | ||
351 | } | |
352 | ||
353 | return SIM_RC_FAIL; | |
354 | } | |
355 | ||
356 | ||
357 | /* "memory" module install handler. | |
358 | ||
359 | This is called via sim_module_install to install the "memory" subsystem | |
360 | into the simulator. */ | |
361 | ||
362 | static MODULE_INIT_FN sim_memory_init; | |
363 | static MODULE_UNINSTALL_FN sim_memory_uninstall; | |
364 | ||
365 | SIM_RC | |
366 | sim_memopt_install (SIM_DESC sd) | |
367 | { | |
368 | SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); | |
369 | sim_add_option_table (sd, memory_options); | |
370 | sim_module_add_uninstall_fn (sd, sim_memory_uninstall); | |
371 | sim_module_add_init_fn (sd, sim_memory_init); | |
372 | return SIM_RC_OK; | |
373 | } | |
374 | ||
375 | ||
376 | /* Uninstall the "memory" subsystem from the simulator. */ | |
377 | ||
378 | static void | |
379 | sim_memory_uninstall (SIM_DESC sd) | |
380 | { | |
381 | /* FIXME: free buffers, etc. */ | |
382 | } | |
383 | ||
384 | ||
385 | static SIM_RC | |
386 | sim_memory_init (SIM_DESC sd) | |
387 | { | |
388 | /* FIXME: anything needed? */ | |
389 | return SIM_RC_OK; | |
390 | } |