1 /* This file is part of the program psim.
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.
30 core_init(engine *system)
32 core *memory = &system->memory;
37 /* blow away old mappings */
38 core_mapping *curr = memory->map[map].first;
39 while (curr != NULL) {
40 core_mapping *tbd = curr;
42 if (tbd->free_buffer) {
43 ASSERT(tbd->buffer != NULL);
48 memory->map[map].first = NULL;
54 STATIC_INLINE_SIM_CORE\
56 new_core_mapping(engine *system,
65 core_mapping *new_mapping = ZALLOC(core_mapping);
67 new_mapping->level = attach;
68 new_mapping->space = space;
69 new_mapping->base = addr;
70 new_mapping->nr_bytes = nr_bytes;
71 new_mapping->bound = addr + (nr_bytes - 1);
72 if (attach == attach_raw_memory) {
73 new_mapping->buffer = buffer;
74 new_mapping->free_buffer = free_buffer;
76 else if (attach >= attach_callback) {
77 new_mapping->device = device;
80 engine_error(system, "new_core_mapping - internal error - unknown attach type %d\n",
87 STATIC_INLINE_SIM_CORE\
89 core_map_attach(engine *system,
94 unsigned nr_bytes, /* host limited */
95 device *client, /*callback/default*/
96 void *buffer, /*raw_memory*/
97 int free_buffer) /*raw_memory*/
99 /* find the insertion point for this additional mapping and then
101 core_mapping *next_mapping;
102 core_mapping **last_mapping;
104 ASSERT((attach >= attach_callback && client != NULL && buffer == NULL && !free_buffer)
105 || (attach == attach_raw_memory && client == NULL && buffer != NULL));
107 /* actually do occasionally get a zero size map */
110 device_error(client, "called on core_map_attach with size zero");
112 engine_error(system, "called on core_map_attach with size zero");
116 /* find the insertion point (between last/next) */
117 next_mapping = access_map->first;
118 last_mapping = &access_map->first;
119 while(next_mapping != NULL
120 && (next_mapping->level < attach
121 || (next_mapping->level == attach
122 && next_mapping->bound < addr))) {
123 /* provided levels are the same */
124 /* assert: next_mapping->base > all bases before next_mapping */
125 /* assert: next_mapping->bound >= all bounds before next_mapping */
126 last_mapping = &next_mapping->next;
127 next_mapping = next_mapping->next;
130 /* check insertion point correct */
131 ASSERT(next_mapping == NULL || next_mapping->level >= attach);
132 if (next_mapping != NULL && next_mapping->level == attach
133 && next_mapping->base < (addr + (nr_bytes - 1))) {
135 device_error(client, "map overlap when attaching %d:0x%lx (%ld)",
136 space, (long)addr, (long)nr_bytes);
138 engine_error(system, "map overlap when attaching %d:0x%lx (%ld)",
139 space, (long)addr, (long)nr_bytes);
143 /* create/insert the new mapping */
144 *last_mapping = new_core_mapping(system,
146 space, addr, nr_bytes,
147 client, buffer, free_buffer);
148 (*last_mapping)->next = next_mapping;
154 core_attach(engine *system,
159 unsigned nr_bytes, /* host limited */
161 void *optional_buffer)
163 core *memory = &system->memory;
167 if ((access & access_read_write_exec) == 0
168 || (access & ~access_read_write_exec) != 0) {
170 device_error(client, "invalid access for core attach");
172 engine_error(system, "invalid access for core attach");
175 /* verify the attach type */
176 if (attach == attach_raw_memory) {
177 if (optional_buffer == NULL) {
178 buffer = zalloc(nr_bytes);
182 buffer = optional_buffer;
186 else if (attach >= attach_callback) {
192 device_error(client, "core_attach - conflicting buffer and attach arguments");
194 engine_error(system, "core_attach - conflicting buffer and attach arguments");
199 /* attach the region to all applicable access maps */
205 if (access & access_read)
206 core_map_attach(system, &memory->map[map],
208 space, addr, nr_bytes,
209 client, buffer, !buffer_freed);
213 if (access & access_write)
214 core_map_attach(system, &memory->map[map],
216 space, addr, nr_bytes,
217 client, buffer, !buffer_freed);
220 case core_execute_map:
221 if (access & access_exec)
222 core_map_attach(system, &memory->map[map],
224 space, addr, nr_bytes,
225 client, buffer, !buffer_freed);
229 engine_error(system, "core_attach - internal error - bad switch");
236 STATIC_INLINE_SIM_CORE\
238 core_map_find_mapping(engine *system,
242 int abort) /*either 0 or 1 - helps inline */
244 core_mapping *mapping = system->memory.map[map].first;
245 ASSERT((addr & (nr_bytes - 1)) == 0); /* must be aligned */
246 ASSERT((addr + (nr_bytes - 1)) >= addr); /* must not wrap */
247 while (mapping != NULL) {
248 if (addr >= mapping->base
249 && (addr + (nr_bytes - 1)) <= mapping->bound)
251 mapping = mapping->next;
254 engine_error(system, "access to unmaped address 0x%x (%d bytes)\n",
260 STATIC_INLINE_SIM_CORE\
262 core_translate(core_mapping *mapping,
265 return (void *)(((char *)mapping->buffer) + addr - mapping->base);
271 core_map_read_buffer(engine *system,
278 while (count < len) {
279 unsigned_word raddr = addr + count;
280 core_mapping *mapping =
281 core_map_find_mapping(system, map,
287 if (mapping->device != NULL) {
288 int nr_bytes = len - count;
289 if (raddr + nr_bytes - 1> mapping->bound)
290 nr_bytes = mapping->bound - raddr + 1;
291 if (device_io_read_buffer(mapping->device,
292 (unsigned_1*)buffer + count,
295 nr_bytes) != nr_bytes)
302 ((unsigned_1*)buffer)[count] =
303 *(unsigned_1*)core_translate(mapping, raddr);
313 core_map_write_buffer(engine *system,
320 while (count < len) {
321 unsigned_word raddr = addr + count;
322 core_mapping *mapping = core_map_find_mapping(system, map,
328 if (WITH_CALLBACK_MEMORY
329 && mapping->device != NULL) {
330 int nr_bytes = len - count;
331 if (raddr + nr_bytes - 1 > mapping->bound)
332 nr_bytes = mapping->bound - raddr + 1;
333 if (device_io_write_buffer(mapping->device,
334 (unsigned_1*)buffer + count,
337 nr_bytes) != nr_bytes)
344 *(unsigned_1*)core_translate(mapping, raddr) =
345 ((unsigned_1*)buffer)[count];
353 /* define the read/write 1/2/4/8/word functions */
356 #include "sim-n-core.h"
360 #include "sim-n-core.h"
364 #include "sim-n-core.h"
368 #include "sim-n-core.h"
372 #include "sim-n-core.h"