Format #instructions with commas
[deliverable/binutils-gdb.git] / sim / ppc / core.c
CommitLineData
cb7a6892
MM
1/* This file is part of the program psim.
2
3 Copyright (C) 1994-1995, 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 2 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
22#ifndef _CORE_C_
23#define _CORE_C_
24
25#ifndef STATIC_INLINE_CORE
26#define STATIC_INLINE_CORE STATIC_INLINE
27#endif
28
dec38dac 29
cb7a6892
MM
30#include "basics.h"
31#include "device_tree.h"
cb7a6892
MM
32#include "core.h"
33
34
dec38dac
MM
35typedef struct _core_mapping core_mapping;
36struct _core_mapping {
37 /* ram map */
38 int free_buffer;
39 void *buffer;
40 /* device map */
41 const device *device;
42 device_io_read_buffer_callback *reader;
43 device_io_write_buffer_callback *writer;
44 /* common */
45 int address_space;
46 unsigned_word base;
47 unsigned_word bound;
48 unsigned nr_bytes;
49 core_mapping *next;
50};
51
52struct _core_map {
53 core_mapping *first;
54 core_mapping *default_map;
55};
56
57typedef enum {
58 core_read_map,
59 core_write_map,
60 core_execute_map,
61 nr_core_map_types,
62} core_map_types;
63
cb7a6892 64struct _core {
dec38dac 65 core_map map[nr_core_map_types];
cb7a6892
MM
66};
67
68
dec38dac
MM
69INLINE_CORE core *
70core_create(void)
71{
72 core *new_core = ZALLOC(core);
73 return new_core;
74}
75
76
cb7a6892 77STATIC_INLINE_CORE void
dec38dac 78core_init(core *memory)
cb7a6892 79{
dec38dac
MM
80 core_map_types access_type;
81 for (access_type = 0;
82 access_type < nr_core_map_types;
83 access_type++) {
84 core_map *map = memory->map + access_type;
85 /* blow away old mappings */
86 core_mapping *curr = map->first;
87 while (curr != NULL) {
88 core_mapping *tbd = curr;
89 curr = curr->next;
90 if (tbd->free_buffer) {
91 ASSERT(tbd->buffer != NULL);
92 zfree(tbd->buffer);
cb7a6892 93 }
dec38dac
MM
94 zfree(tbd);
95 }
96 map->first = NULL;
97 /* blow away the default */
98 if (map->default_map != NULL) {
99 ASSERT(map->default_map->buffer == NULL);
100 zfree(map->default_map);
cb7a6892 101 }
dec38dac 102 map->default_map = NULL;
cb7a6892
MM
103 }
104}
105
106
dec38dac
MM
107
108/* the core has three sub mappings that the more efficient
109 read/write fixed quantity functions use */
110
111INLINE_CORE core_map *
112core_readable(core *memory)
cb7a6892 113{
dec38dac 114 return memory->map + core_read_map;
cb7a6892
MM
115}
116
dec38dac
MM
117INLINE_CORE core_map *
118core_writeable(core *memory)
119{
120 return memory->map + core_write_map;
121}
cb7a6892 122
dec38dac
MM
123INLINE_CORE core_map *
124core_executable(core *memory)
cb7a6892 125{
dec38dac 126 return memory->map + core_execute_map;
cb7a6892
MM
127}
128
dec38dac
MM
129
130
131STATIC_INLINE_CORE core_mapping *
132new_core_mapping(attach_type attach,
133 int address_space,
134 unsigned_word addr,
135 unsigned nr_bytes,
136 const device *device,
137 void *buffer,
138 int free_buffer)
cb7a6892 139{
dec38dac
MM
140 core_mapping *new_mapping = ZALLOC(core_mapping);
141 switch (attach) {
142 case attach_default:
143 case attach_callback:
144 new_mapping->device = device;
145 new_mapping->reader = device->callback->io_read_buffer;
146 new_mapping->writer = device->callback->io_write_buffer;
147 break;
148 case attach_raw_memory:
149 new_mapping->buffer = buffer;
150 new_mapping->free_buffer = free_buffer;
151 break;
152 default:
153 error("new_core_mapping() - internal error - unknown attach type %d\n",
154 attach);
cb7a6892 155 }
dec38dac
MM
156 /* common */
157 new_mapping->address_space = address_space;
158 new_mapping->base = addr;
159 new_mapping->nr_bytes = nr_bytes;
160 new_mapping->bound = addr + (nr_bytes - 1);
161 return new_mapping;
cb7a6892
MM
162}
163
dec38dac
MM
164
165STATIC_INLINE_CORE void
166core_map_attach(core_map *access_map,
167 attach_type attach,
168 int address_space,
169 unsigned_word addr,
170 unsigned nr_bytes, /* host limited */
171 const device *device, /*callback/default*/
172 void *buffer, /*raw_memory*/
173 int free_buffer) /*raw_memory*/
cb7a6892 174{
dec38dac
MM
175 if (attach == attach_default) {
176 if (access_map->default_map != NULL)
177 error("core_map_attach() default mapping already in place\n");
178 ASSERT(buffer == NULL);
179 access_map->default_map = new_core_mapping(attach,
180 address_space, addr, nr_bytes,
181 device, buffer, free_buffer);
cb7a6892 182 }
dec38dac
MM
183 else {
184 /* find the insertion point for this additional mapping and insert */
185 core_mapping *next_mapping;
186 core_mapping **last_mapping;
187
188 /* actually do occasionally get a zero size map */
189 if (nr_bytes == 0)
190 error("core_map_attach() size == 0\n");
191
192 /* find the insertion point (between last/next) */
193 next_mapping = access_map->first;
194 last_mapping = &access_map->first;
195 while(next_mapping != NULL && next_mapping->bound < addr) {
196 /* assert: next_mapping->base > all bases before next_mapping */
197 /* assert: next_mapping->bound >= all bounds before next_mapping */
198 last_mapping = &next_mapping->next;
199 next_mapping = next_mapping->next;
cb7a6892 200 }
cb7a6892 201
dec38dac
MM
202 /* check insertion point correct */
203 if (next_mapping != NULL && next_mapping->base < (addr + (nr_bytes - 1))) {
204 error("core_map_attach() map overlap\n");
205 }
cb7a6892 206
dec38dac
MM
207 /* create/insert the new mapping */
208 *last_mapping = new_core_mapping(attach,
209 address_space, addr, nr_bytes,
210 device, buffer, free_buffer);
211 (*last_mapping)->next = next_mapping;
212 }
cb7a6892
MM
213}
214
215
cb7a6892 216INLINE_CORE void
dec38dac
MM
217core_attach(core *memory,
218 attach_type attach,
219 int address_space,
220 access_type access,
221 unsigned_word addr,
222 unsigned nr_bytes, /* host limited */
223 const device *device) /*callback/default*/
cb7a6892 224{
dec38dac
MM
225 core_map_types access_map;
226 int free_buffer = 0;
227 void *buffer = NULL;
228 ASSERT(attach == attach_default || nr_bytes > 0);
229 if (attach == attach_raw_memory)
230 buffer = zalloc(nr_bytes);
231 for (access_map = 0;
232 access_map < nr_core_map_types;
233 access_map++) {
234 switch (access_map) {
235 case core_read_map:
236 if (access & access_read)
237 core_map_attach(memory->map + access_map,
238 attach,
239 address_space, addr, nr_bytes,
240 device, buffer, !free_buffer);
241 free_buffer ++;
242 break;
243 case core_write_map:
244 if (access & access_write)
245 core_map_attach(memory->map + access_map,
246 attach,
247 address_space, addr, nr_bytes,
248 device, buffer, !free_buffer);
249 free_buffer ++;
250 break;
251 case core_execute_map:
252 if (access & access_exec)
253 core_map_attach(memory->map + access_map,
254 attach,
255 address_space, addr, nr_bytes,
256 device, buffer, !free_buffer);
257 free_buffer ++;
258 break;
259 default:
260 error("core_attach() internal error\n");
261 break;
262 }
263 }
264 ASSERT(free_buffer > 0); /* must attach to at least one thing */
cb7a6892
MM
265}
266
267
dec38dac
MM
268STATIC_INLINE_CORE core_mapping *
269core_map_find_mapping(core_map *map,
270 unsigned_word addr,
271 unsigned nr_bytes,
272 cpu *processor,
273 unsigned_word cia,
274 int abort) /*either 0 or 1 - helps inline */
cb7a6892 275{
dec38dac
MM
276 core_mapping *mapping = map->first;
277 ASSERT((addr & (nr_bytes - 1)) == 0); /* must be aligned */
278 ASSERT((addr + (nr_bytes - 1)) >= addr); /* must not wrap */
279 while (mapping != NULL) {
280 if (addr >= mapping->base
281 && (addr + (nr_bytes - 1)) <= mapping->bound)
282 return mapping;
283 mapping = mapping->next;
284 }
285 if (map->default_map != NULL)
286 return map->default_map;
287 if (abort)
288 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",
289 addr, nr_bytes, processor, cia);
290 return NULL;
cb7a6892
MM
291}
292
293
dec38dac
MM
294STATIC_INLINE_CORE void *
295core_translate(core_mapping *mapping,
296 unsigned_word addr)
cb7a6892 297{
dec38dac 298 return mapping->buffer + addr - mapping->base;
cb7a6892
MM
299}
300
dec38dac
MM
301
302INLINE_CORE unsigned
303core_map_read_buffer(core_map *map,
304 void *buffer,
305 unsigned_word addr,
306 unsigned len)
cb7a6892 307{
dec38dac
MM
308 unsigned count;
309 unsigned_1 byte;
310 for (count = 0; count < len; count++) {
311 unsigned_word raddr = addr + count;
312 core_mapping *mapping =
313 core_map_find_mapping(map,
314 raddr, 1,
315 NULL, /*processor*/
316 0, /*cia*/
317 0); /*dont-abort*/
318 if (mapping == NULL)
319 break;
320 if (mapping->reader != NULL) {
321 if (mapping->reader(mapping->device,
322 &byte,
323 mapping->address_space,
324 raddr - mapping->base,
325 1, /* nr_bytes */
326 0, /*processor*/
327 0 /*cpu*/) != 1)
328 break;
329 }
330 else
331 byte = *(unsigned_1*)core_translate(mapping,
332 raddr);
333 ((unsigned_1*)buffer)[count] = T2H_1(byte);
334 }
335 return count;
cb7a6892
MM
336}
337
338
dec38dac
MM
339INLINE_CORE unsigned
340core_map_write_buffer(core_map *map,
341 const void *buffer,
342 unsigned_word addr,
343 unsigned len)
cb7a6892 344{
dec38dac
MM
345 unsigned count;
346 unsigned_1 byte;
347 for (count = 0; count < len; count++) {
348 unsigned_word raddr = addr + count;
349 core_mapping *mapping = core_map_find_mapping(map,
350 raddr, 1,
351 NULL, /*processor*/
352 0, /*cia*/
353 0); /*dont-abort*/
354 if (mapping == NULL)
355 break;
356 byte = H2T_1(((unsigned_1*)buffer)[count]);
357 if (mapping->writer != NULL) {
358 if (mapping->writer(mapping->device,
359 &byte,
360 mapping->address_space,
361 raddr - mapping->base,
362 1, /*nr_bytes*/
363 0, /*processor*/
364 0 /*cpu*/) != 1)
365 break;
366 }
367 else
368 *(unsigned_1*)core_translate(mapping, raddr) = byte;
369 }
370 return count;
cb7a6892
MM
371}
372
cb7a6892
MM
373
374
dec38dac
MM
375/* Top level core(root) device: core@garbage
376
377 The core device captures incomming dma requests and changes them to
378 outgoing io requests. */
cb7a6892 379
dec38dac
MM
380STATIC_INLINE_CORE void
381core_init_callback(const device *me,
382 psim *system)
cb7a6892 383{
dec38dac
MM
384 core *memory = (core*)me->data;
385 core_init(memory);
cb7a6892
MM
386}
387
388
dec38dac
MM
389STATIC_INLINE_CORE void
390core_attach_address_callback(const device *me,
391 const char *name,
392 attach_type attach,
393 int address_space,
394 unsigned_word addr,
395 unsigned nr_bytes,
396 access_type access,
397 const device *who) /*callback/default*/
cb7a6892 398{
dec38dac
MM
399 core *memory = (core*)me->data;
400 unsigned_word device_address;
401 if (address_space != 0)
402 error("core_attach_address_callback() invalid address space\n");
403 core_attach(memory,
404 attach,
405 address_space,
406 access,
407 addr,
408 nr_bytes,
409 who);
cb7a6892
MM
410}
411
412
dec38dac
MM
413STATIC_INLINE_CORE unsigned
414core_dma_read_buffer_callback(const device *me,
415 void *target,
416 int address_space,
417 unsigned_word offset,
418 unsigned nr_bytes)
cb7a6892 419{
dec38dac
MM
420 core *memory = (core*)me->data;
421 return core_map_read_buffer(core_readable(memory),
422 target,
423 offset,
424 nr_bytes);
cb7a6892
MM
425}
426
427
dec38dac
MM
428STATIC_INLINE_CORE unsigned
429core_dma_write_buffer_callback(const device *me,
430 const void *source,
431 int address_space,
432 unsigned_word offset,
433 unsigned nr_bytes,
434 int violate_read_only_section)
cb7a6892 435{
dec38dac
MM
436 core *memory = (core*)me->data;
437 core_map *map = (violate_read_only_section
438 ? core_readable(memory)
439 : core_writeable(memory));
440 return core_map_write_buffer(map,
441 source,
442 offset,
443 nr_bytes);
cb7a6892
MM
444}
445
446
dec38dac
MM
447static device_callbacks const core_callbacks = {
448 core_init_callback,
449 core_attach_address_callback,
450 unimp_device_detach_address,
451 unimp_device_io_read_buffer,
452 unimp_device_io_write_buffer,
453 core_dma_read_buffer_callback,
454 core_dma_write_buffer_callback,
455 unimp_device_attach_interrupt,
456 unimp_device_detach_interrupt,
457 unimp_device_interrupt,
458 unimp_device_interrupt_ack,
459 unimp_device_ioctl,
460};
461
462
463INLINE_CORE const device *
464core_device_create(core *memory)
cb7a6892 465{
dec38dac 466 return device_create_from("core", memory, &core_callbacks, NULL);
cb7a6892
MM
467}
468
dec38dac
MM
469
470
471/* define the read/write 1/2/4/8/word functions */
472
473#undef N
474#define N 1
475#include "core_n.h"
476
477#undef N
478#define N 2
479#include "core_n.h"
480
481#undef N
482#define N 4
483#include "core_n.h"
484
485#undef N
486#define N 8
487#include "core_n.h"
488
489#undef N
490#define N word
491#include "core_n.h"
492
493#endif /* _CORE_C_ */
This page took 0.046171 seconds and 4 git commands to generate.