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