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