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