Update
[gdb.git] / sim / ppc / corefile.c
blob00295bb2a62251a1ad70cc50f2c3d35f7a1fa4e2
1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #ifndef _CORE_C_
23 #define _CORE_C_
25 #include "basics.h"
26 #include "device_table.h"
27 #include "corefile.h"
29 typedef struct _core_mapping core_mapping;
30 struct _core_mapping {
31 /* common */
32 int level;
33 int space;
34 unsigned_word base;
35 unsigned_word bound;
36 unsigned nr_bytes;
37 /* memory map */
38 void *free_buffer;
39 void *buffer;
40 /* callback map */
41 device *device;
42 /* growth */
43 core_mapping *next;
46 struct _core_map {
47 core_mapping *first;
50 typedef enum {
51 core_read_map,
52 core_write_map,
53 core_execute_map,
54 nr_core_map_types,
55 } core_map_types;
57 struct _core {
58 core_map map[nr_core_map_types];
62 INLINE_CORE\
63 (core *)
64 core_create(void)
66 return ZALLOC(core);
70 INLINE_CORE\
71 (core *)
72 core_from_device(device *root)
74 root = device_root(root);
75 ASSERT(strcmp(device_name(root), "core") == 0);
76 return device_data(root);
80 INLINE_CORE\
81 (void)
82 core_init(core *memory)
84 core_map_types access_type;
85 for (access_type = 0;
86 access_type < nr_core_map_types;
87 access_type++) {
88 core_map *map = memory->map + access_type;
89 /* blow away old mappings */
90 core_mapping *curr = map->first;
91 while (curr != NULL) {
92 core_mapping *tbd = curr;
93 curr = curr->next;
94 if (tbd->free_buffer != NULL) {
95 ASSERT(tbd->buffer != NULL);
96 zfree(tbd->free_buffer);
98 zfree(tbd);
100 map->first = NULL;
106 /* the core has three sub mappings that the more efficient
107 read/write fixed quantity functions use */
109 INLINE_CORE\
110 (core_map *)
111 core_readable(core *memory)
113 return memory->map + core_read_map;
116 INLINE_CORE\
117 (core_map *)
118 core_writeable(core *memory)
120 return memory->map + core_write_map;
123 INLINE_CORE\
124 (core_map *)
125 core_executable(core *memory)
127 return memory->map + core_execute_map;
132 STATIC_INLINE_CORE\
133 (core_mapping *)
134 new_core_mapping(attach_type attach,
135 int space,
136 unsigned_word addr,
137 unsigned nr_bytes,
138 device *device,
139 void *buffer,
140 void *free_buffer)
142 core_mapping *new_mapping = ZALLOC(core_mapping);
143 /* common */
144 new_mapping->level = attach;
145 new_mapping->space = space;
146 new_mapping->base = addr;
147 new_mapping->nr_bytes = nr_bytes;
148 new_mapping->bound = addr + (nr_bytes - 1);
149 if (attach == attach_raw_memory) {
150 new_mapping->buffer = buffer;
151 new_mapping->free_buffer = free_buffer;
153 else if (attach >= attach_callback) {
154 new_mapping->device = device;
156 else {
157 error("new_core_mapping() - internal error - unknown attach type %d\n",
158 attach);
160 return new_mapping;
164 STATIC_INLINE_CORE\
165 (void)
166 core_map_attach(core_map *access_map,
167 attach_type attach,
168 int space,
169 unsigned_word addr,
170 unsigned nr_bytes, /* host limited */
171 device *client, /*callback/default*/
172 void *buffer, /*raw_memory*/
173 void *free_buffer) /*raw_memory*/
175 /* find the insertion point for this additional mapping and insert */
176 core_mapping *next_mapping;
177 core_mapping **last_mapping;
179 /* actually do occasionally get a zero size map */
180 if (nr_bytes == 0) {
181 device_error(client, "called on core_map_attach() with size zero");
184 /* find the insertion point (between last/next) */
185 next_mapping = access_map->first;
186 last_mapping = &access_map->first;
187 while(next_mapping != NULL
188 && (next_mapping->level < attach
189 || (next_mapping->level == attach
190 && next_mapping->bound < addr))) {
191 /* provided levels are the same */
192 /* assert: next_mapping->base > all bases before next_mapping */
193 /* assert: next_mapping->bound >= all bounds before next_mapping */
194 last_mapping = &next_mapping->next;
195 next_mapping = next_mapping->next;
198 /* check insertion point correct */
199 ASSERT(next_mapping == NULL || next_mapping->level >= attach);
200 if (next_mapping != NULL && next_mapping->level == attach
201 && next_mapping->base < (addr + (nr_bytes - 1))) {
202 device_error(client, "map overlap when attaching %d:0x%lx (%ld)",
203 space, (long)addr, (long)nr_bytes);
206 /* create/insert the new mapping */
207 *last_mapping = new_core_mapping(attach,
208 space, addr, nr_bytes,
209 client, buffer, free_buffer);
210 (*last_mapping)->next = next_mapping;
214 INLINE_CORE\
215 (void)
216 core_attach(core *memory,
217 attach_type attach,
218 int space,
219 access_type access,
220 unsigned_word addr,
221 unsigned nr_bytes, /* host limited */
222 device *client) /*callback/default*/
224 core_map_types access_map;
225 void *buffer;
226 void *free_buffer;
227 if (attach == attach_raw_memory) {
228 /* Padd out the raw buffer to ensure that ADDR starts on a
229 correctly aligned boundary */
230 int padding = (addr % sizeof (unsigned64));
231 free_buffer = zalloc(nr_bytes + padding);
232 buffer = (char*)free_buffer + padding;
234 else {
235 buffer = NULL;
236 free_buffer = &buffer; /* marker for assertion */
238 for (access_map = 0;
239 access_map < nr_core_map_types;
240 access_map++) {
241 switch (access_map) {
242 case core_read_map:
243 if (access & access_read)
244 core_map_attach(memory->map + access_map,
245 attach,
246 space, addr, nr_bytes,
247 client, buffer, free_buffer);
248 free_buffer = NULL;
249 break;
250 case core_write_map:
251 if (access & access_write)
252 core_map_attach(memory->map + access_map,
253 attach,
254 space, addr, nr_bytes,
255 client, buffer, free_buffer);
256 free_buffer = NULL;
257 break;
258 case core_execute_map:
259 if (access & access_exec)
260 core_map_attach(memory->map + access_map,
261 attach,
262 space, addr, nr_bytes,
263 client, buffer, free_buffer);
264 free_buffer = NULL;
265 break;
266 default:
267 error("core_attach() internal error\n");
268 break;
271 /* allocated buffer must attach to at least one thing */
272 ASSERT(free_buffer == NULL);
276 STATIC_INLINE_CORE\
277 (core_mapping *)
278 core_map_find_mapping(core_map *map,
279 unsigned_word addr,
280 unsigned nr_bytes,
281 cpu *processor,
282 unsigned_word cia,
283 int abort) /*either 0 or 1 - helps inline */
285 core_mapping *mapping = map->first;
286 ASSERT((addr & (nr_bytes - 1)) == 0); /* must be aligned */
287 ASSERT((addr + (nr_bytes - 1)) >= addr); /* must not wrap */
288 while (mapping != NULL) {
289 if (addr >= mapping->base
290 && (addr + (nr_bytes - 1)) <= mapping->bound)
291 return mapping;
292 mapping = mapping->next;
294 if (abort)
295 error("core_find_mapping() - access to unmaped address, attach a default map to handle this - addr=0x%x nr_bytes=0x%x processor=0x%x cia=0x%x\n",
296 addr, nr_bytes, processor, cia);
297 return NULL;
301 STATIC_INLINE_CORE\
302 (void *)
303 core_translate(core_mapping *mapping,
304 unsigned_word addr)
306 return (void *)(((char *)mapping->buffer) + addr - mapping->base);
310 INLINE_CORE\
311 (unsigned)
312 core_map_read_buffer(core_map *map,
313 void *buffer,
314 unsigned_word addr,
315 unsigned len)
317 unsigned count = 0;
318 while (count < len) {
319 unsigned_word raddr = addr + count;
320 core_mapping *mapping =
321 core_map_find_mapping(map,
322 raddr, 1,
323 NULL, /*processor*/
324 0, /*cia*/
325 0); /*dont-abort*/
326 if (mapping == NULL)
327 break;
328 if (mapping->device != NULL) {
329 int nr_bytes = len - count;
330 if (raddr + nr_bytes - 1> mapping->bound)
331 nr_bytes = mapping->bound - raddr + 1;
332 if (device_io_read_buffer(mapping->device,
333 (unsigned_1*)buffer + count,
334 mapping->space,
335 raddr,
336 nr_bytes,
337 0, /*processor*/
338 0 /*cpu*/) != nr_bytes)
339 break;
340 count += nr_bytes;
342 else {
343 ((unsigned_1*)buffer)[count] =
344 *(unsigned_1*)core_translate(mapping, raddr);
345 count += 1;
348 return count;
352 INLINE_CORE\
353 (unsigned)
354 core_map_write_buffer(core_map *map,
355 const void *buffer,
356 unsigned_word addr,
357 unsigned len)
359 unsigned count = 0;
360 while (count < len) {
361 unsigned_word raddr = addr + count;
362 core_mapping *mapping = core_map_find_mapping(map,
363 raddr, 1,
364 NULL, /*processor*/
365 0, /*cia*/
366 0); /*dont-abort*/
367 if (mapping == NULL)
368 break;
369 if (mapping->device != NULL) {
370 int nr_bytes = len - count;
371 if (raddr + nr_bytes - 1 > mapping->bound)
372 nr_bytes = mapping->bound - raddr + 1;
373 if (device_io_write_buffer(mapping->device,
374 (unsigned_1*)buffer + count,
375 mapping->space,
376 raddr,
377 nr_bytes,
378 0, /*processor*/
379 0 /*cpu*/) != nr_bytes)
380 break;
381 count += nr_bytes;
383 else {
384 *(unsigned_1*)core_translate(mapping, raddr) =
385 ((unsigned_1*)buffer)[count];
386 count += 1;
389 return count;
393 /* define the read/write 1/2/4/8/word functions */
395 #define N 1
396 #include "corefile-n.h"
397 #undef N
399 #define N 2
400 #include "corefile-n.h"
401 #undef N
403 #define N 4
404 #include "corefile-n.h"
405 #undef N
407 #define N 8
408 #include "corefile-n.h"
409 #undef N
411 #define N word
412 #include "corefile-n.h"
413 #undef N
415 #endif /* _CORE_C_ */