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