Update to new config scheme
[deliverable/binutils-gdb.git] / sim / ppc / memory_map.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 _MEMORY_MAP_C_
23#define _MEMORY_MAP_C_
24
25#ifndef STATIC_INLINE_MEMORY_MAP
26#define STATIC_INLINE_MEMORY_MAP STATIC_INLINE
27#endif
28
29
30#include "basics.h"
31#include "device_tree.h"
32#include "memory_map.h"
33#include "interrupts.h"
34
35
36typedef struct _memory_mapping memory_mapping;
37struct _memory_mapping {
38 /* ram map */
39 void *buffer;
40 /* device map */
41 device_node *device;
42 device_reader_callback *reader;
43 device_writer_callback *writer;
44 /* common */
45 unsigned_word base;
46 unsigned_word bound;
47 unsigned_word size;
48 struct _memory_mapping *next;
49};
50
51struct _memory_map {
52 memory_mapping *first;
53};
54
55INLINE_MEMORY_MAP memory_map *
56new_memory_map(void)
57{
58 memory_map *new_map;
59 new_map = ZALLOC(memory_map);
60 return new_map;
61}
62
63STATIC_INLINE_MEMORY_MAP void
64memory_map_add_memory(memory_map *map,
65 device_node *device,
66 device_reader_callback *reader,
67 device_writer_callback *writer,
68 void *buffer,
69 unsigned_word base,
70 unsigned size)
71{
72 memory_mapping *new_mapping;
73 memory_mapping *next_mapping;
74 memory_mapping **last_mapping;
75
76 /* actually do occasionally get a zero size map */
77 if (size == 0)
78 return;
79
80 new_mapping = ZALLOC(memory_mapping);
81
82 /* ram */
83 new_mapping->buffer = buffer;
84 /* devices */
85 new_mapping->device = device;
86 new_mapping->reader = reader;
87 new_mapping->writer = writer;
88 /* common */
89 new_mapping->base = base;
90 new_mapping->size = size;
91 new_mapping->bound = base + size;
92
93 /* find the insertion point (between last/next) */
94 next_mapping = map->first;
95 last_mapping = &map->first;
96 while(next_mapping != NULL && next_mapping->bound <= new_mapping->base) {
97 /* assert: new_mapping->base > all bases before next_mapping */
98 /* assert: new_mapping->bound >= all bounds before next_mapping */
99 last_mapping = &next_mapping->next;
100 next_mapping = next_mapping->next;
101 }
102
103 /* check insertion point correct */
104 if (next_mapping != NULL && next_mapping->base < new_mapping->bound) {
105 error("memory_map_add_callback_memory() internal error - map overlap\n");
106 }
107
108 /* insert the new mapping */
109 *last_mapping = new_mapping;
110 new_mapping->next = next_mapping;
111
112}
113
114
115INLINE_MEMORY_MAP void
116memory_map_add_callback_memory(memory_map *map,
117 device_node *device,
118 device_reader_callback *reader,
119 device_writer_callback *writer,
120 unsigned_word base,
121 unsigned size)
122{
123 memory_map_add_memory(map, device, reader, writer, NULL, base, size);
124}
125
126INLINE_MEMORY_MAP void
127memory_map_add_raw_memory(memory_map *map,
128 void *buffer,
129 unsigned_word base,
130 unsigned size)
131{
132 memory_map_add_memory(map, NULL, NULL, NULL, buffer, base, size);
133}
134
135
136
137
138STATIC_INLINE_MEMORY_MAP memory_mapping *
139memory_map_find_mapping(memory_map *map,
140 unsigned_word addr,
141 unsigned nr_bytes,
142 int abort,
143 cpu *processor,
144 unsigned_word cia)
145{
146 memory_mapping *mapping = map->first;
147 ASSERT((addr & (nr_bytes-1)) == 0);
148 while (1) {
149 if (addr >= mapping->base
150 && (addr + nr_bytes) <= mapping->bound)
151 break;
152 mapping = mapping->next;
153 if (mapping == NULL) {
154 if (abort) {
155 switch (CURRENT_ENVIRONMENT) {
156 case VIRTUAL_ENVIRONMENT:
157 data_storage_interrupt(processor,
158 cia,
159 addr,
160 vea_storage_interrupt,
161 0/* doesnt matter */);
162 break;
163 default:
164 error("memory_map_find_mapping() - %s%x%s%s%s%s%s",
165 "access to undefined address 0x", addr, "\n",
166 "this code should be passing back up the device tree an\n",
167 "abort event (with processor attached). Somewhere in\n",
168 "the device tree this would be caught and either halt,\n",
169 "interrupt, or reset the processor\n");
170 }
171 return NULL;
172 }
173 else
174 return NULL;
175 }
176 }
177 return mapping;
178}
179
180
181STATIC_INLINE_MEMORY_MAP void *
182memory_map_translate(memory_mapping *mapping,
183 unsigned_word addr)
184{
185 return mapping->buffer + addr - mapping->base;
186}
187
188
189INLINE_MEMORY_MAP unsigned
190memory_map_read_buffer(memory_map *map,
191 void *buffer,
192 unsigned_word addr,
193 unsigned len,
194 transfer_mode mode)
195{
196 unsigned count;
197 unsigned_1 byte;
198 for (count = 0; count < len; count++) {
199 unsigned pos = 0;
200 unsigned_word raddr = addr + count;
201 memory_mapping *mapping =
202 memory_map_find_mapping(map, raddr, 1,
203 0/*abort*/,
204 0, 0/*processor, cia*/);
205 if (mapping == NULL)
206 break;
207 if (mode == raw_transfer ||
208 CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER)
209 pos = count;
210 else if (mode == cooked_transfer)
211 pos = len-count-1;
212 else
213 error("memory_map_read_buffer() - transfer mode unknown\n");
214 if (mapping->reader != NULL)
215 /* hope it doesn't barf */
216 byte = mapping->reader(mapping->device,
217 raddr - mapping->base,
218 1,
219 0, 0/*processor, cia*/);
220 else
221 byte = *(unsigned_1*)memory_map_translate(mapping,
222 raddr);
223 ((unsigned_1*)buffer)[pos] = T2H_1(byte);
224 }
225 return count;
226}
227
228
229INLINE_MEMORY_MAP unsigned
230memory_map_write_buffer(memory_map *map,
231 const void *buffer,
232 unsigned_word addr,
233 unsigned len,
234 transfer_mode mode)
235{
236 unsigned count;
237 unsigned_1 byte;
238 for (count = 0; count < len; count++) {
239 unsigned pos = 0;
240 unsigned_word raddr = addr + count;
241 memory_mapping *mapping =
242 memory_map_find_mapping(map, raddr, 1,
243 0/*abort*/,
244 0, 0/*processor, cia*/);
245 if (mapping == NULL)
246 break;
247 if (mode == raw_transfer ||
248 CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER)
249 pos = count;
250 else if (mode == cooked_transfer)
251 pos = len-count-1;
252 else
253 error("memory_map_write_buffer() - transfer mode unknown\n");
254 byte = H2T_1(((unsigned_1*)buffer)[pos]);
255 if (mapping->writer != NULL)
256 /* hope it doesn't barf */
257 mapping->writer(mapping->device,
258 raddr - mapping->base,
259 1,
260 byte,
261 0, 0/*processor, cia*/);
262 else
263 *(unsigned_1*)memory_map_translate(mapping, raddr) = byte;
264 }
265 return count;
266}
267
268
269INLINE_MEMORY_MAP unsigned
270memory_map_zero(memory_map *map,
271 unsigned_word addr,
272 unsigned len)
273{
274 unsigned pos;
275 for (pos = 0; pos < len; pos++) {
276 unsigned_word raddr = addr + pos;
277 memory_mapping *mapping =
278 memory_map_find_mapping(map, raddr, 1,
279 0/*abort*/,
280 0, 0/*processor, cia*/);
281 if (mapping == NULL)
282 break;
283 if (mapping->writer != NULL)
284 mapping->writer(mapping->device,
285 raddr - mapping->base,
286 1,
287 0,
288 0, 0/*processor, cia*/);
289 else
290 *(unsigned_1*)memory_map_translate(mapping, raddr) = 0;
291 }
292 return pos;
293}
294
295
296#define DEFINE_MEMORY_MAP_READ_N(N) \
297INLINE_MEMORY_MAP unsigned_##N \
298memory_map_read_##N(memory_map *map, \
299 unsigned_word addr, \
300 cpu *processor, \
301 unsigned_word cia) \
302{ \
303 memory_mapping *mapping = memory_map_find_mapping(map, addr, \
304 sizeof(unsigned_##N), \
305 1, \
306 processor, \
307 cia); \
308 if (WITH_CALLBACK_MEMORY && mapping->reader != NULL) \
309 return ((unsigned_##N) \
310 mapping->reader(mapping->device, \
311 addr - mapping->base, \
312 sizeof(unsigned_##N), \
313 processor, \
314 cia)); \
315 else \
316 return T2H_##N(*(unsigned_##N*)memory_map_translate(mapping, addr)); \
317}
318
319DEFINE_MEMORY_MAP_READ_N(1)
320DEFINE_MEMORY_MAP_READ_N(2)
321DEFINE_MEMORY_MAP_READ_N(4)
322DEFINE_MEMORY_MAP_READ_N(8)
323DEFINE_MEMORY_MAP_READ_N(word)
324
325#define DEFINE_MEMORY_MAP_WRITE_N(N) \
326INLINE_MEMORY_MAP void \
327memory_map_write_##N(memory_map *map, \
328 unsigned_word addr, \
329 unsigned_##N val, \
330 cpu *processor, \
331 unsigned_word cia) \
332{ \
333 memory_mapping *mapping = memory_map_find_mapping(map, addr, \
334 sizeof(unsigned_##N), \
335 1, \
336 processor, \
337 cia); \
338 if (WITH_CALLBACK_MEMORY && mapping->writer != NULL) \
339 mapping->writer(mapping->device, \
340 addr - mapping->base, \
341 sizeof(unsigned_##N), \
342 val, \
343 processor, \
344 cia); \
345 else \
346 *(unsigned_##N*)memory_map_translate(mapping, addr) = H2T_##N(val); \
347}
348
349DEFINE_MEMORY_MAP_WRITE_N(1)
350DEFINE_MEMORY_MAP_WRITE_N(2)
351DEFINE_MEMORY_MAP_WRITE_N(4)
352DEFINE_MEMORY_MAP_WRITE_N(8)
353DEFINE_MEMORY_MAP_WRITE_N(word)
354
355#endif /* _MEMORY_MAP_C_ */
This page took 0.035347 seconds and 4 git commands to generate.