xref: /netbsd-src/external/gpl3/gdb/dist/sim/ppc/corefile.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*  This file is part of the program psim.
2 
3     Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
4 
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 3 of the License, or
8     (at your option) any later version.
9 
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.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, see <http://www.gnu.org/licenses/>.
17 
18     */
19 
20 
21 #ifndef _CORE_C_
22 #define _CORE_C_
23 
24 #include "basics.h"
25 #include "device_table.h"
26 #include "corefile.h"
27 
28 typedef struct _core_mapping core_mapping;
29 struct _core_mapping {
30   /* common */
31   int level;
32   int space;
33   unsigned_word base;
34   unsigned_word bound;
35   unsigned nr_bytes;
36   /* memory map */
37   void *free_buffer;
38   void *buffer;
39   /* callback map */
40   device *device;
41   /* growth */
42   core_mapping *next;
43 };
44 
45 struct _core_map {
46   core_mapping *first;
47 };
48 
49 typedef enum {
50   core_read_map,
51   core_write_map,
52   core_execute_map,
53   nr_core_map_types,
54 } core_map_types;
55 
56 struct _core {
57   core_map map[nr_core_map_types];
58 };
59 
60 
61 INLINE_CORE\
62 (core *)
63 core_create(void)
64 {
65   return ZALLOC(core);
66 }
67 
68 
69 INLINE_CORE\
70 (core *)
71 core_from_device(device *root)
72 {
73   root = device_root(root);
74   ASSERT(strcmp(device_name(root), "core") == 0);
75   return device_data(root);
76 }
77 
78 
79 INLINE_CORE\
80 (void)
81 core_init(core *memory)
82 {
83   core_map_types access_type;
84   for (access_type = 0;
85        access_type < nr_core_map_types;
86        access_type++) {
87     core_map *map = memory->map + access_type;
88     /* blow away old mappings */
89     core_mapping *curr = map->first;
90     while (curr != NULL) {
91       core_mapping *tbd = curr;
92       curr = curr->next;
93       if (tbd->free_buffer != NULL) {
94 	ASSERT(tbd->buffer != NULL);
95 	free(tbd->free_buffer);
96       }
97       free(tbd);
98     }
99     map->first = NULL;
100   }
101 }
102 
103 
104 
105 /* the core has three sub mappings that the more efficient
106    read/write fixed quantity functions use */
107 
108 INLINE_CORE\
109 (core_map *)
110 core_readable(core *memory)
111 {
112   return memory->map + core_read_map;
113 }
114 
115 INLINE_CORE\
116 (core_map *)
117 core_writeable(core *memory)
118 {
119   return memory->map + core_write_map;
120 }
121 
122 INLINE_CORE\
123 (core_map *)
124 core_executable(core *memory)
125 {
126   return memory->map + core_execute_map;
127 }
128 
129 
130 
131 STATIC_INLINE_CORE\
132 (core_mapping *)
133 new_core_mapping(attach_type attach,
134 		 int space,
135 		 unsigned_word addr,
136 		 unsigned nr_bytes,
137 		 device *device,
138 		 void *buffer,
139 		 void *free_buffer)
140 {
141   core_mapping *new_mapping = ZALLOC(core_mapping);
142   /* common */
143   new_mapping->level = attach;
144   new_mapping->space = space;
145   new_mapping->base = addr;
146   new_mapping->nr_bytes = nr_bytes;
147   new_mapping->bound = addr + (nr_bytes - 1);
148   if (attach == attach_raw_memory) {
149     new_mapping->buffer = buffer;
150     new_mapping->free_buffer = free_buffer;
151   }
152   else if (attach >= attach_callback) {
153     new_mapping->device = device;
154   }
155   else {
156     error("new_core_mapping() - internal error - unknown attach type %d\n",
157 	  attach);
158   }
159   return new_mapping;
160 }
161 
162 
163 STATIC_INLINE_CORE\
164 (void)
165 core_map_attach(core_map *access_map,
166 		attach_type attach,
167 		int space,
168 		unsigned_word addr,
169 		unsigned nr_bytes, /* host limited */
170 		device *client, /*callback/default*/
171 		void *buffer, /*raw_memory*/
172 		void *free_buffer) /*raw_memory*/
173 {
174   /* find the insertion point for this additional mapping and insert */
175   core_mapping *next_mapping;
176   core_mapping **last_mapping;
177 
178   /* actually do occasionally get a zero size map */
179   if (nr_bytes == 0) {
180     device_error(client, "called on core_map_attach() with size zero");
181   }
182 
183   /* find the insertion point (between last/next) */
184   next_mapping = access_map->first;
185   last_mapping = &access_map->first;
186   while(next_mapping != NULL
187 	&& (next_mapping->level < attach
188 	    || (next_mapping->level == attach
189 		&& next_mapping->bound < addr))) {
190     /* provided levels are the same */
191     /* assert: next_mapping->base > all bases before next_mapping */
192     /* assert: next_mapping->bound >= all bounds before next_mapping */
193     last_mapping = &next_mapping->next;
194     next_mapping = next_mapping->next;
195   }
196 
197   /* check insertion point correct */
198   ASSERT(next_mapping == NULL || next_mapping->level >= attach);
199   if (next_mapping != NULL && next_mapping->level == attach
200       && next_mapping->base < (addr + (nr_bytes - 1))) {
201     device_error(client, "map overlap when attaching %d:0x%lx (%ld)",
202 		 space, (long)addr, (long)nr_bytes);
203   }
204 
205   /* create/insert the new mapping */
206   *last_mapping = new_core_mapping(attach,
207 				   space, addr, nr_bytes,
208 				   client, buffer, free_buffer);
209   (*last_mapping)->next = next_mapping;
210 }
211 
212 
213 INLINE_CORE\
214 (void)
215 core_attach(core *memory,
216 	    attach_type attach,
217 	    int space,
218 	    access_type access,
219 	    unsigned_word addr,
220 	    unsigned nr_bytes, /* host limited */
221 	    device *client) /*callback/default*/
222 {
223   core_map_types access_map;
224   void *buffer;
225   void *free_buffer;
226   if (attach == attach_raw_memory) {
227     /* Padd out the raw buffer to ensure that ADDR starts on a
228        correctly aligned boundary */
229     int padding = (addr % sizeof (unsigned64));
230     free_buffer = zalloc(nr_bytes + padding);
231     buffer = (char*)free_buffer + padding;
232   }
233   else {
234     buffer = NULL;
235     free_buffer = &buffer; /* marker for assertion */
236   }
237   for (access_map = 0;
238        access_map < nr_core_map_types;
239        access_map++) {
240     switch (access_map) {
241     case core_read_map:
242       if (access & access_read)
243 	core_map_attach(memory->map + access_map,
244 			attach,
245 			space, addr, nr_bytes,
246 			client, buffer, free_buffer);
247       free_buffer = NULL;
248       break;
249     case core_write_map:
250       if (access & access_write)
251 	core_map_attach(memory->map + access_map,
252 			attach,
253 			space, addr, nr_bytes,
254 			client, buffer, free_buffer);
255       free_buffer = NULL;
256       break;
257     case core_execute_map:
258       if (access & access_exec)
259 	core_map_attach(memory->map + access_map,
260 			attach,
261 			space, addr, nr_bytes,
262 			client, buffer, free_buffer);
263       free_buffer = NULL;
264       break;
265     default:
266       error("core_attach() internal error\n");
267       break;
268     }
269   }
270   /* allocated buffer must attach to at least one thing */
271   ASSERT(free_buffer == NULL);
272 }
273 
274 
275 STATIC_INLINE_CORE\
276 (core_mapping *)
277 core_map_find_mapping(core_map *map,
278 		      unsigned_word addr,
279 		      unsigned nr_bytes,
280 		      cpu *processor,
281 		      unsigned_word cia,
282 		      int abort) /*either 0 or 1 - helps inline */
283 {
284   core_mapping *mapping = map->first;
285   ASSERT((addr & (nr_bytes - 1)) == 0); /* must be aligned */
286   ASSERT((addr + (nr_bytes - 1)) >= addr); /* must not wrap */
287   while (mapping != NULL) {
288     if (addr >= mapping->base
289 	&& (addr + (nr_bytes - 1)) <= mapping->bound)
290       return mapping;
291     mapping = mapping->next;
292   }
293   if (abort)
294     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",
295 	  addr, nr_bytes, processor, cia);
296   return NULL;
297 }
298 
299 
300 STATIC_INLINE_CORE\
301 (void *)
302 core_translate(core_mapping *mapping,
303 	       unsigned_word addr)
304 {
305   return (void *)(((char *)mapping->buffer) + addr - mapping->base);
306 }
307 
308 
309 INLINE_CORE\
310 (unsigned)
311 core_map_read_buffer(core_map *map,
312 		     void *buffer,
313 		     unsigned_word addr,
314 		     unsigned len)
315 {
316   unsigned count = 0;
317   while (count < len) {
318     unsigned_word raddr = addr + count;
319     core_mapping *mapping =
320       core_map_find_mapping(map,
321 			    raddr, 1,
322 			    NULL, /*processor*/
323 			    0, /*cia*/
324 			    0); /*dont-abort*/
325     if (mapping == NULL)
326       break;
327     if (mapping->device != NULL) {
328       int nr_bytes = len - count;
329       if (raddr + nr_bytes - 1> mapping->bound)
330 	nr_bytes = mapping->bound - raddr + 1;
331       if (device_io_read_buffer(mapping->device,
332 				(unsigned_1*)buffer + count,
333 				mapping->space,
334 				raddr,
335 				nr_bytes,
336 				0, /*processor*/
337 				0 /*cpu*/) != nr_bytes)
338 	break;
339       count += nr_bytes;
340     }
341     else {
342       ((unsigned_1*)buffer)[count] =
343 	*(unsigned_1*)core_translate(mapping, raddr);
344       count += 1;
345     }
346   }
347   return count;
348 }
349 
350 
351 INLINE_CORE\
352 (unsigned)
353 core_map_write_buffer(core_map *map,
354 		      const void *buffer,
355 		      unsigned_word addr,
356 		      unsigned len)
357 {
358   unsigned count = 0;
359   while (count < len) {
360     unsigned_word raddr = addr + count;
361     core_mapping *mapping = core_map_find_mapping(map,
362 						  raddr, 1,
363 						  NULL, /*processor*/
364 						  0, /*cia*/
365 						  0); /*dont-abort*/
366     if (mapping == NULL)
367       break;
368     if (mapping->device != NULL) {
369       int nr_bytes = len - count;
370       if (raddr + nr_bytes - 1 > mapping->bound)
371 	nr_bytes = mapping->bound - raddr + 1;
372       if (device_io_write_buffer(mapping->device,
373 				 (unsigned_1*)buffer + count,
374 				 mapping->space,
375 				 raddr,
376 				 nr_bytes,
377 				 0, /*processor*/
378 				 0 /*cpu*/) != nr_bytes)
379 	break;
380       count += nr_bytes;
381     }
382     else {
383       *(unsigned_1*)core_translate(mapping, raddr) =
384 	((unsigned_1*)buffer)[count];
385       count += 1;
386     }
387   }
388   return count;
389 }
390 
391 
392 /* define the read/write 1/2/4/8/word functions */
393 
394 #define N 1
395 #include "corefile-n.h"
396 #undef N
397 
398 #define N 2
399 #include "corefile-n.h"
400 #undef N
401 
402 #define N 4
403 #include "corefile-n.h"
404 #undef N
405 
406 #define N 8
407 #include "corefile-n.h"
408 #undef N
409 
410 #define N word
411 #include "corefile-n.h"
412 #undef N
413 
414 #endif /* _CORE_C_ */
415