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