b9a018b997a2e61da7a48228eb816a38971d2473
[deliverable/binutils-gdb.git] / sim / arm / armvirt.c
1 /* armvirt.c -- ARMulator virtual memory interace: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18 /* This file contains a complete ARMulator memory model, modelling a
19 "virtual memory" system. A much simpler model can be found in armfast.c,
20 and that model goes faster too, but has a fixed amount of memory. This
21 model's memory has 64K pages, allocated on demand from a 64K entry page
22 table. The routines PutWord and GetWord implement this. Pages are never
23 freed as they might be needed again. A single area of memory may be
24 defined to generate aborts. */
25
26 #include "armopts.h"
27 #include "armdefs.h"
28 #include "ansidecl.h"
29
30 #ifdef VALIDATE /* for running the validate suite */
31 #define TUBE 48 * 1024 * 1024 /* write a char on the screen */
32 #define ABORTS 1
33 #endif
34
35 /* #define ABORTS */
36
37 #ifdef ABORTS /* the memory system will abort */
38 /* For the old test suite Abort between 32 Kbytes and 32 Mbytes
39 For the new test suite Abort between 8 Mbytes and 26 Mbytes */
40 /* #define LOWABORT 32 * 1024
41 #define HIGHABORT 32 * 1024 * 1024 */
42 #define LOWABORT 8 * 1024 * 1024
43 #define HIGHABORT 26 * 1024 * 1024
44
45 #endif
46
47 #define NUMPAGES 64 * 1024
48 #define PAGESIZE 64 * 1024
49 #define PAGEBITS 16
50 #define OFFSETBITS 0xffff
51
52 int SWI_vector_installed = FALSE;
53
54 /***************************************************************************\
55 * Get a Word from Virtual Memory, maybe allocating the page *
56 \***************************************************************************/
57
58 static ARMword
59 GetWord (ARMul_State * state, ARMword address)
60 {
61 ARMword page;
62 ARMword offset;
63 ARMword **pagetable;
64 ARMword *pageptr;
65
66 page = address >> PAGEBITS;
67 offset = (address & OFFSETBITS) >> 2;
68 pagetable = (ARMword **) state->MemDataPtr;
69 pageptr = *(pagetable + page);
70
71 if (pageptr == NULL)
72 {
73 pageptr = (ARMword *) malloc (PAGESIZE);
74
75 if (pageptr == NULL)
76 {
77 perror ("ARMulator can't allocate VM page");
78 exit (12);
79 }
80
81 *(pagetable + page) = pageptr;
82 }
83
84 return *(pageptr + offset);
85 }
86
87 /***************************************************************************\
88 * Put a Word into Virtual Memory, maybe allocating the page *
89 \***************************************************************************/
90
91 static void
92 PutWord (ARMul_State * state, ARMword address, ARMword data)
93 {
94 ARMword page;
95 ARMword offset;
96 ARMword **pagetable;
97 ARMword *pageptr;
98
99 page = address >> PAGEBITS;
100 offset = (address & OFFSETBITS) >> 2;
101 pagetable = (ARMword **) state->MemDataPtr;
102 pageptr = *(pagetable + page);
103
104 if (pageptr == NULL)
105 {
106 pageptr = (ARMword *) malloc (PAGESIZE);
107 if (pageptr == NULL)
108 {
109 perror ("ARMulator can't allocate VM page");
110 exit (13);
111 }
112
113 *(pagetable + page) = pageptr;
114 }
115
116 if (address == 0x8)
117 SWI_vector_installed = TRUE;
118
119 *(pageptr + offset) = data;
120 }
121
122 /***************************************************************************\
123 * Initialise the memory interface *
124 \***************************************************************************/
125
126 unsigned
127 ARMul_MemoryInit (ARMul_State * state, unsigned long initmemsize)
128 {
129 ARMword **pagetable;
130 unsigned page;
131
132 if (initmemsize)
133 state->MemSize = initmemsize;
134
135 pagetable = (ARMword **) malloc (sizeof (ARMword) * NUMPAGES);
136
137 if (pagetable == NULL)
138 return FALSE;
139
140 for (page = 0; page < NUMPAGES; page++)
141 *(pagetable + page) = NULL;
142
143 state->MemDataPtr = (unsigned char *) pagetable;
144
145 ARMul_ConsolePrint (state, ", 4 Gb memory");
146
147 return TRUE;
148 }
149
150 /***************************************************************************\
151 * Remove the memory interface *
152 \***************************************************************************/
153
154 void
155 ARMul_MemoryExit (ARMul_State * state)
156 {
157 ARMword page;
158 ARMword **pagetable;
159 ARMword *pageptr;
160
161 pagetable = (ARMword **) state->MemDataPtr;
162 for (page = 0; page < NUMPAGES; page++)
163 {
164 pageptr = *(pagetable + page);
165 if (pageptr != NULL)
166 free ((char *) pageptr);
167 }
168 free ((char *) pagetable);
169 return;
170 }
171
172 /***************************************************************************\
173 * ReLoad Instruction *
174 \***************************************************************************/
175
176 ARMword
177 ARMul_ReLoadInstr (ARMul_State * state, ARMword address, ARMword isize)
178 {
179 #ifdef ABORTS
180 if (address >= LOWABORT && address < HIGHABORT)
181 {
182 ARMul_PREFETCHABORT (address);
183 return ARMul_ABORTWORD;
184 }
185 else
186 {
187 ARMul_CLEARABORT;
188 }
189 #endif
190
191 if ((isize == 2) && (address & 0x2))
192 {
193 /* We return the next two halfwords: */
194 ARMword lo = GetWord (state, address);
195 ARMword hi = GetWord (state, address + 4);
196
197 if (state->bigendSig == HIGH)
198 return (lo << 16) | (hi >> 16);
199 else
200 return ((hi & 0xFFFF) << 16) | (lo >> 16);
201 }
202
203 return GetWord (state, address);
204 }
205
206 /***************************************************************************\
207 * Load Instruction, Sequential Cycle *
208 \***************************************************************************/
209
210 ARMword ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize)
211 {
212 state->NumScycles++;
213
214 #ifdef HOURGLASS
215 if ((state->NumScycles & HOURGLASS_RATE) == 0)
216 {
217 HOURGLASS;
218 }
219 #endif
220
221 return ARMul_ReLoadInstr (state, address, isize);
222 }
223
224 /***************************************************************************\
225 * Load Instruction, Non Sequential Cycle *
226 \***************************************************************************/
227
228 ARMword ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize)
229 {
230 state->NumNcycles++;
231
232 return ARMul_ReLoadInstr (state, address, isize);
233 }
234
235 /***************************************************************************\
236 * Read Word (but don't tell anyone!) *
237 \***************************************************************************/
238
239 ARMword ARMul_ReadWord (ARMul_State * state, ARMword address)
240 {
241 #ifdef ABORTS
242 if (address >= LOWABORT && address < HIGHABORT)
243 {
244 ARMul_DATAABORT (address);
245 return ARMul_ABORTWORD;
246 }
247 else
248 {
249 ARMul_CLEARABORT;
250 }
251 #endif
252
253 return GetWord (state, address);
254 }
255
256 /***************************************************************************\
257 * Load Word, Sequential Cycle *
258 \***************************************************************************/
259
260 ARMword ARMul_LoadWordS (ARMul_State * state, ARMword address)
261 {
262 state->NumScycles++;
263
264 return ARMul_ReadWord (state, address);
265 }
266
267 /***************************************************************************\
268 * Load Word, Non Sequential Cycle *
269 \***************************************************************************/
270
271 ARMword ARMul_LoadWordN (ARMul_State * state, ARMword address)
272 {
273 state->NumNcycles++;
274
275 return ARMul_ReadWord (state, address);
276 }
277
278 /***************************************************************************\
279 * Load Halfword, (Non Sequential Cycle) *
280 \***************************************************************************/
281
282 ARMword ARMul_LoadHalfWord (ARMul_State * state, ARMword address)
283 {
284 ARMword temp, offset;
285
286 state->NumNcycles++;
287
288 temp = ARMul_ReadWord (state, address);
289 offset = (((ARMword) state->bigendSig * 2) ^ (address & 2)) << 3; /* bit offset into the word */
290
291 return (temp >> offset) & 0xffff;
292 }
293
294 /***************************************************************************\
295 * Read Byte (but don't tell anyone!) *
296 \***************************************************************************/
297
298 ARMword ARMul_ReadByte (ARMul_State * state, ARMword address)
299 {
300 ARMword temp, offset;
301
302 temp = ARMul_ReadWord (state, address);
303 offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */
304
305 return (temp >> offset & 0xffL);
306 }
307
308 /***************************************************************************\
309 * Load Byte, (Non Sequential Cycle) *
310 \***************************************************************************/
311
312 ARMword ARMul_LoadByte (ARMul_State * state, ARMword address)
313 {
314 state->NumNcycles++;
315
316 return ARMul_ReadByte (state, address);
317 }
318
319 /***************************************************************************\
320 * Write Word (but don't tell anyone!) *
321 \***************************************************************************/
322
323 void
324 ARMul_WriteWord (ARMul_State * state, ARMword address, ARMword data)
325 {
326 #ifdef ABORTS
327 if (address >= LOWABORT && address < HIGHABORT)
328 {
329 ARMul_DATAABORT (address);
330 return;
331 }
332 else
333 {
334 ARMul_CLEARABORT;
335 }
336 #endif
337
338 PutWord (state, address, data);
339 }
340
341 /***************************************************************************\
342 * Store Word, Sequential Cycle *
343 \***************************************************************************/
344
345 void
346 ARMul_StoreWordS (ARMul_State * state, ARMword address, ARMword data)
347 {
348 state->NumScycles++;
349
350 ARMul_WriteWord (state, address, data);
351 }
352
353 /***************************************************************************\
354 * Store Word, Non Sequential Cycle *
355 \***************************************************************************/
356
357 void
358 ARMul_StoreWordN (ARMul_State * state, ARMword address, ARMword data)
359 {
360 state->NumNcycles++;
361
362 ARMul_WriteWord (state, address, data);
363 }
364
365 /***************************************************************************\
366 * Store HalfWord, (Non Sequential Cycle) *
367 \***************************************************************************/
368
369 void
370 ARMul_StoreHalfWord (ARMul_State * state, ARMword address, ARMword data)
371 {
372 ARMword temp, offset;
373
374 state->NumNcycles++;
375
376 #ifdef VALIDATE
377 if (address == TUBE)
378 {
379 if (data == 4)
380 state->Emulate = FALSE;
381 else
382 (void) putc ((char) data, stderr); /* Write Char */
383 return;
384 }
385 #endif
386
387 temp = ARMul_ReadWord (state, address);
388 offset = (((ARMword) state->bigendSig * 2) ^ (address & 2)) << 3; /* bit offset into the word */
389
390 PutWord (state, address,
391 (temp & ~(0xffffL << offset)) | ((data & 0xffffL) << offset));
392 }
393
394 /***************************************************************************\
395 * Write Byte (but don't tell anyone!) *
396 \***************************************************************************/
397
398 void
399 ARMul_WriteByte (ARMul_State * state, ARMword address, ARMword data)
400 {
401 ARMword temp, offset;
402
403 temp = ARMul_ReadWord (state, address);
404 offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */
405
406 PutWord (state, address,
407 (temp & ~(0xffL << offset)) | ((data & 0xffL) << offset));
408 }
409
410 /***************************************************************************\
411 * Store Byte, (Non Sequential Cycle) *
412 \***************************************************************************/
413
414 void
415 ARMul_StoreByte (ARMul_State * state, ARMword address, ARMword data)
416 {
417 state->NumNcycles++;
418
419 #ifdef VALIDATE
420 if (address == TUBE)
421 {
422 if (data == 4)
423 state->Emulate = FALSE;
424 else
425 (void) putc ((char) data, stderr); /* Write Char */
426 return;
427 }
428 #endif
429
430 ARMul_WriteByte (state, address, data);
431 }
432
433 /***************************************************************************\
434 * Swap Word, (Two Non Sequential Cycles) *
435 \***************************************************************************/
436
437 ARMword ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data)
438 {
439 ARMword temp;
440
441 state->NumNcycles++;
442
443 temp = ARMul_ReadWord (state, address);
444
445 state->NumNcycles++;
446
447 PutWord (state, address, data);
448
449 return temp;
450 }
451
452 /***************************************************************************\
453 * Swap Byte, (Two Non Sequential Cycles) *
454 \***************************************************************************/
455
456 ARMword ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data)
457 {
458 ARMword temp;
459
460 temp = ARMul_LoadByte (state, address);
461 ARMul_StoreByte (state, address, data);
462
463 return temp;
464 }
465
466 /***************************************************************************\
467 * Count I Cycles *
468 \***************************************************************************/
469
470 void
471 ARMul_Icycles (ARMul_State * state, unsigned number, ARMword address ATTRIBUTE_UNUSED)
472 {
473 state->NumIcycles += number;
474 ARMul_CLEARABORT;
475 }
476
477 /***************************************************************************\
478 * Count C Cycles *
479 \***************************************************************************/
480
481 void
482 ARMul_Ccycles (ARMul_State * state, unsigned number, ARMword address ATTRIBUTE_UNUSED)
483 {
484 state->NumCcycles += number;
485 ARMul_CLEARABORT;
486 }
This page took 0.040481 seconds and 4 git commands to generate.