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 | ||
aca1adee | 36 | /* Memory command line options. */ |
a34abff8 AC |
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 | 182 | static SIM_RC |
966df580 DE |
183 | memory_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, |
184 | char *arg, int is_command) | |
a34abff8 AC |
185 | { |
186 | switch (opt) | |
187 | { | |
188 | ||
189 | case OPTION_MEMORY_DELETE: | |
fcc86d82 | 190 | if (strcasecmp (arg, "all") == 0) |
6dbaff8f AC |
191 | { |
192 | while (STATE_MEMOPT (sd) != NULL) | |
fcc86d82 AC |
193 | do_memopt_delete (sd, |
194 | STATE_MEMOPT (sd)->level, | |
195 | STATE_MEMOPT (sd)->space, | |
196 | STATE_MEMOPT (sd)->addr); | |
6dbaff8f AC |
197 | return SIM_RC_OK; |
198 | } | |
199 | else | |
200 | { | |
fcc86d82 AC |
201 | int level = 0; |
202 | int space = 0; | |
203 | address_word addr = 0; | |
204 | parse_addr (arg, &level, &space, &addr); | |
205 | return do_memopt_delete (sd, level, space, addr); | |
6dbaff8f | 206 | } |
a34abff8 AC |
207 | |
208 | case OPTION_MEMORY_REGION: | |
209 | { | |
210 | char *chp = arg; | |
fcc86d82 AC |
211 | int level = 0; |
212 | int space = 0; | |
a34abff8 AC |
213 | address_word addr = 0; |
214 | address_word nr_bytes = 0; | |
215 | unsigned modulo = 0; | |
a34abff8 | 216 | /* parse the arguments */ |
fcc86d82 | 217 | chp = parse_addr (chp, &level, &space, &addr); |
a34abff8 AC |
218 | if (*chp != ',') |
219 | { | |
220 | sim_io_eprintf (sd, "Missing size for memory-region\n"); | |
221 | return SIM_RC_FAIL; | |
222 | } | |
fcc86d82 AC |
223 | chp = parse_size (chp + 1, &nr_bytes, &modulo); |
224 | /* old style */ | |
a34abff8 | 225 | if (*chp == ',') |
fcc86d82 | 226 | modulo = strtoul (chp + 1, &chp, 0); |
6dbaff8f | 227 | /* try to attach/insert it */ |
fcc86d82 AC |
228 | do_memopt_add (sd, level, space, addr, nr_bytes, modulo, |
229 | &STATE_MEMOPT (sd), NULL); | |
a34abff8 AC |
230 | return SIM_RC_OK; |
231 | } | |
232 | ||
233 | case OPTION_MEMORY_ALIAS: | |
234 | { | |
6dbaff8f | 235 | char *chp = arg; |
fcc86d82 AC |
236 | int level = 0; |
237 | int space = 0; | |
6dbaff8f AC |
238 | address_word addr = 0; |
239 | address_word nr_bytes = 0; | |
fcc86d82 | 240 | unsigned modulo = 0; |
6dbaff8f AC |
241 | sim_memopt *entry; |
242 | /* parse the arguments */ | |
fcc86d82 | 243 | chp = parse_addr (chp, &level, &space, &addr); |
6dbaff8f AC |
244 | if (*chp != ',') |
245 | { | |
246 | sim_io_eprintf (sd, "Missing size for memory-region\n"); | |
247 | return SIM_RC_FAIL; | |
248 | } | |
fcc86d82 | 249 | chp = parse_size (chp + 1, &nr_bytes, &modulo); |
6dbaff8f | 250 | /* try to attach/insert the main record */ |
fcc86d82 | 251 | entry = do_memopt_add (sd, level, space, addr, nr_bytes, modulo, |
966df580 DE |
252 | &STATE_MEMOPT (sd), |
253 | zalloc (modulo ? modulo : nr_bytes)); | |
6dbaff8f AC |
254 | /* now attach all the aliases */ |
255 | while (*chp == ',') | |
256 | { | |
fcc86d82 AC |
257 | int a_level = level; |
258 | int a_space = space; | |
259 | address_word a_addr = addr; | |
966df580 | 260 | chp = parse_addr (chp + 1, &a_level, &a_space, &a_addr); |
fcc86d82 | 261 | do_memopt_add (sd, a_level, a_space, a_addr, nr_bytes, modulo, |
6dbaff8f AC |
262 | &entry->alias, entry->buffer); |
263 | } | |
264 | return SIM_RC_OK; | |
a34abff8 AC |
265 | } |
266 | ||
267 | case OPTION_MEMORY_SIZE: | |
268 | { | |
fcc86d82 AC |
269 | int level = 0; |
270 | int space = 0; | |
271 | address_word addr = 0; | |
272 | address_word nr_bytes = 0; | |
273 | unsigned modulo = 0; | |
274 | /* parse the arguments */ | |
275 | parse_size (arg, &nr_bytes, &modulo); | |
6dbaff8f | 276 | /* try to attach/insert it */ |
fcc86d82 | 277 | do_memopt_add (sd, level, space, addr, nr_bytes, modulo, |
6dbaff8f AC |
278 | &STATE_MEMOPT (sd), NULL); |
279 | return SIM_RC_OK; | |
a34abff8 AC |
280 | } |
281 | ||
282 | case OPTION_MEMORY_CLEAR: | |
283 | { | |
284 | sim_memopt *entry; | |
285 | for (entry = STATE_MEMOPT (sd); entry != NULL; entry = entry->next) | |
286 | { | |
287 | sim_memopt *alias; | |
288 | for (alias = entry; alias != NULL; alias = alias->next) | |
289 | { | |
290 | unsigned8 zero = 0; | |
291 | address_word nr_bytes; | |
292 | if (alias->modulo != 0) | |
293 | nr_bytes = alias->modulo; | |
294 | else | |
295 | nr_bytes = alias->nr_bytes; | |
296 | sim_core_write_buffer (sd, NULL, sim_core_write_map, | |
297 | &zero, | |
298 | alias->addr + nr_bytes, | |
299 | sizeof (zero)); | |
300 | ||
301 | } | |
302 | } | |
303 | return SIM_RC_OK; | |
304 | break; | |
305 | } | |
306 | ||
307 | case OPTION_MEMORY_INFO: | |
308 | { | |
309 | sim_memopt *entry; | |
310 | sim_io_printf (sd, "Memory maps:\n"); | |
311 | for (entry = STATE_MEMOPT (sd); entry != NULL; entry = entry->next) | |
312 | { | |
313 | sim_memopt *alias; | |
314 | sim_io_printf (sd, " memory"); | |
315 | if (entry->alias == NULL) | |
fcc86d82 | 316 | sim_io_printf (sd, " region "); |
a34abff8 | 317 | else |
fcc86d82 AC |
318 | sim_io_printf (sd, " alias "); |
319 | if (entry->space != 0) | |
320 | sim_io_printf (sd, "0x%lx:", (long) entry->space); | |
966df580 | 321 | sim_io_printf (sd, "0x%08lx", (long) entry->addr); |
fcc86d82 AC |
322 | if (entry->level != 0) |
323 | sim_io_printf (sd, "@0x%lx", (long) entry->level); | |
324 | sim_io_printf (sd, ",0x%lx", | |
325 | (long) entry->nr_bytes); | |
326 | if (entry->modulo != 0) | |
327 | sim_io_printf (sd, "%%0x%lx", (long) entry->modulo); | |
328 | for (alias = entry->alias; | |
329 | alias != NULL; | |
330 | alias = alias->next) | |
a34abff8 | 331 | { |
fcc86d82 AC |
332 | if (alias->space != 0) |
333 | sim_io_printf (sd, "0x%lx:", (long) alias->space); | |
966df580 | 334 | sim_io_printf (sd, ",0x%08lx", (long) alias->addr); |
fcc86d82 AC |
335 | if (alias->level != 0) |
336 | sim_io_printf (sd, "@0x%lx", (long) alias->level); | |
a34abff8 AC |
337 | } |
338 | sim_io_printf (sd, "\n"); | |
339 | } | |
340 | return SIM_RC_OK; | |
341 | break; | |
342 | } | |
343 | ||
344 | default: | |
aca1adee | 345 | sim_io_eprintf (sd, "Unknown memory option %d\n", opt); |
a34abff8 AC |
346 | return SIM_RC_FAIL; |
347 | ||
348 | } | |
349 | ||
350 | return SIM_RC_FAIL; | |
351 | } | |
352 | ||
353 | ||
354 | /* "memory" module install handler. | |
355 | ||
356 | This is called via sim_module_install to install the "memory" subsystem | |
357 | into the simulator. */ | |
358 | ||
359 | static MODULE_INIT_FN sim_memory_init; | |
360 | static MODULE_UNINSTALL_FN sim_memory_uninstall; | |
361 | ||
362 | SIM_RC | |
363 | sim_memopt_install (SIM_DESC sd) | |
364 | { | |
365 | SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); | |
966df580 | 366 | sim_add_option_table (sd, NULL, memory_options); |
a34abff8 AC |
367 | sim_module_add_uninstall_fn (sd, sim_memory_uninstall); |
368 | sim_module_add_init_fn (sd, sim_memory_init); | |
369 | return SIM_RC_OK; | |
370 | } | |
371 | ||
372 | ||
373 | /* Uninstall the "memory" subsystem from the simulator. */ | |
374 | ||
375 | static void | |
376 | sim_memory_uninstall (SIM_DESC sd) | |
377 | { | |
378 | /* FIXME: free buffers, etc. */ | |
379 | } | |
380 | ||
381 | ||
382 | static SIM_RC | |
383 | sim_memory_init (SIM_DESC sd) | |
384 | { | |
385 | /* FIXME: anything needed? */ | |
386 | return SIM_RC_OK; | |
387 | } |