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