1 /* armvirt.c -- ARMulator virtual memory interace: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
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.
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.
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. */
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. */
31 #ifdef VALIDATE /* for running the validate suite */
32 #define TUBE 48 * 1024 * 1024 /* write a char on the screen */
38 #ifdef ABORTS /* the memory system will abort */
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
48 #define NUMPAGES 64 * 1024
49 #define PAGESIZE 64 * 1024
51 #define OFFSETBITS 0xffff
53 int SWI_vector_installed = FALSE;
55 /***************************************************************************\
56 * Get a Word from Virtual Memory, maybe allocating the page *
57 \***************************************************************************/
60 GetWord (ARMul_State * state, ARMword address, int check)
67 page = address >> PAGEBITS;
68 offset = (address & OFFSETBITS) >> 2;
69 pagetable = (ARMword **) state->MemDataPtr;
70 pageptr = *(pagetable + page);
74 pageptr = (ARMword *) malloc (PAGESIZE);
78 perror ("ARMulator can't allocate VM page");
82 *(pagetable + page) = pageptr;
85 return *(pageptr + offset);
88 /***************************************************************************\
89 * Put a Word into Virtual Memory, maybe allocating the page *
90 \***************************************************************************/
93 PutWord (ARMul_State * state, ARMword address, ARMword data, int check)
100 page = address >> PAGEBITS;
101 offset = (address & OFFSETBITS) >> 2;
102 pagetable = (ARMword **) state->MemDataPtr;
103 pageptr = *(pagetable + page);
107 pageptr = (ARMword *) malloc (PAGESIZE);
110 perror ("ARMulator can't allocate VM page");
114 *(pagetable + page) = pageptr;
118 SWI_vector_installed = TRUE;
120 *(pageptr + offset) = data;
123 /***************************************************************************\
124 * Initialise the memory interface *
125 \***************************************************************************/
128 ARMul_MemoryInit (ARMul_State * state, unsigned long initmemsize)
134 state->MemSize = initmemsize;
136 pagetable = (ARMword **) malloc (sizeof (ARMword) * NUMPAGES);
138 if (pagetable == NULL)
141 for (page = 0; page < NUMPAGES; page++)
142 *(pagetable + page) = NULL;
144 state->MemDataPtr = (unsigned char *) pagetable;
146 ARMul_ConsolePrint (state, ", 4 Gb memory");
151 /***************************************************************************\
152 * Remove the memory interface *
153 \***************************************************************************/
156 ARMul_MemoryExit (ARMul_State * state)
162 pagetable = (ARMword **) state->MemDataPtr;
163 for (page = 0; page < NUMPAGES; page++)
165 pageptr = *(pagetable + page);
167 free ((char *) pageptr);
169 free ((char *) pagetable);
173 /***************************************************************************\
174 * ReLoad Instruction *
175 \***************************************************************************/
178 ARMul_ReLoadInstr (ARMul_State * state, ARMword address, ARMword isize)
181 if (address >= LOWABORT && address < HIGHABORT)
183 ARMul_PREFETCHABORT (address);
184 return ARMul_ABORTWORD;
192 if ((isize == 2) && (address & 0x2))
194 /* We return the next two halfwords: */
195 ARMword lo = GetWord (state, address, FALSE);
196 ARMword hi = GetWord (state, address + 4, FALSE);
198 if (state->bigendSig == HIGH)
199 return (lo << 16) | (hi >> 16);
201 return ((hi & 0xFFFF) << 16) | (lo >> 16);
204 return GetWord (state, address, TRUE);
207 /***************************************************************************\
208 * Load Instruction, Sequential Cycle *
209 \***************************************************************************/
211 ARMword ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize)
216 if ((state->NumScycles & HOURGLASS_RATE) == 0)
222 return ARMul_ReLoadInstr (state, address, isize);
225 /***************************************************************************\
226 * Load Instruction, Non Sequential Cycle *
227 \***************************************************************************/
229 ARMword ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize)
233 return ARMul_ReLoadInstr (state, address, isize);
236 /***************************************************************************\
237 * Read Word (but don't tell anyone!) *
238 \***************************************************************************/
240 ARMword ARMul_ReadWord (ARMul_State * state, ARMword address)
243 if (address >= LOWABORT && address < HIGHABORT)
245 ARMul_DATAABORT (address);
246 return ARMul_ABORTWORD;
254 return GetWord (state, address, TRUE);
257 /***************************************************************************\
258 * Load Word, Sequential Cycle *
259 \***************************************************************************/
261 ARMword ARMul_LoadWordS (ARMul_State * state, ARMword address)
265 return ARMul_ReadWord (state, address);
268 /***************************************************************************\
269 * Load Word, Non Sequential Cycle *
270 \***************************************************************************/
272 ARMword ARMul_LoadWordN (ARMul_State * state, ARMword address)
276 return ARMul_ReadWord (state, address);
279 /***************************************************************************\
280 * Load Halfword, (Non Sequential Cycle) *
281 \***************************************************************************/
283 ARMword ARMul_LoadHalfWord (ARMul_State * state, ARMword address)
285 ARMword temp, offset;
289 temp = ARMul_ReadWord (state, address);
290 offset = (((ARMword) state->bigendSig * 2) ^ (address & 2)) << 3; /* bit offset into the word */
292 return (temp >> offset) & 0xffff;
295 /***************************************************************************\
296 * Read Byte (but don't tell anyone!) *
297 \***************************************************************************/
299 ARMword ARMul_ReadByte (ARMul_State * state, ARMword address)
301 ARMword temp, offset;
303 temp = ARMul_ReadWord (state, address);
304 offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */
306 return (temp >> offset & 0xffL);
309 /***************************************************************************\
310 * Load Byte, (Non Sequential Cycle) *
311 \***************************************************************************/
313 ARMword ARMul_LoadByte (ARMul_State * state, ARMword address)
317 return ARMul_ReadByte (state, address);
320 /***************************************************************************\
321 * Write Word (but don't tell anyone!) *
322 \***************************************************************************/
325 ARMul_WriteWord (ARMul_State * state, ARMword address, ARMword data)
328 if (address >= LOWABORT && address < HIGHABORT)
330 ARMul_DATAABORT (address);
339 PutWord (state, address, data, TRUE);
342 /***************************************************************************\
343 * Store Word, Sequential Cycle *
344 \***************************************************************************/
347 ARMul_StoreWordS (ARMul_State * state, ARMword address, ARMword data)
351 ARMul_WriteWord (state, address, data);
354 /***************************************************************************\
355 * Store Word, Non Sequential Cycle *
356 \***************************************************************************/
359 ARMul_StoreWordN (ARMul_State * state, ARMword address, ARMword data)
363 ARMul_WriteWord (state, address, data);
366 /***************************************************************************\
367 * Store HalfWord, (Non Sequential Cycle) *
368 \***************************************************************************/
371 ARMul_StoreHalfWord (ARMul_State * state, ARMword address, ARMword data)
373 ARMword temp, offset;
381 state->Emulate = FALSE;
383 (void) putc ((char) data, stderr); /* Write Char */
388 temp = ARMul_ReadWord (state, address);
389 offset = (((ARMword) state->bigendSig * 2) ^ (address & 2)) << 3; /* bit offset into the word */
391 PutWord (state, address,
392 (temp & ~(0xffffL << offset)) | ((data & 0xffffL) << offset),
396 /***************************************************************************\
397 * Write Byte (but don't tell anyone!) *
398 \***************************************************************************/
401 ARMul_WriteByte (ARMul_State * state, ARMword address, ARMword data)
403 ARMword temp, offset;
405 temp = ARMul_ReadWord (state, address);
406 offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */
408 PutWord (state, address,
409 (temp & ~(0xffL << offset)) | ((data & 0xffL) << offset),
413 /***************************************************************************\
414 * Store Byte, (Non Sequential Cycle) *
415 \***************************************************************************/
418 ARMul_StoreByte (ARMul_State * state, ARMword address, ARMword data)
426 state->Emulate = FALSE;
428 (void) putc ((char) data, stderr); /* Write Char */
433 ARMul_WriteByte (state, address, data);
436 /***************************************************************************\
437 * Swap Word, (Two Non Sequential Cycles) *
438 \***************************************************************************/
440 ARMword ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data)
446 temp = ARMul_ReadWord (state, address);
450 PutWord (state, address, data, TRUE);
455 /***************************************************************************\
456 * Swap Byte, (Two Non Sequential Cycles) *
457 \***************************************************************************/
459 ARMword ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data)
463 temp = ARMul_LoadByte (state, address);
464 ARMul_StoreByte (state, address, data);
469 /***************************************************************************\
471 \***************************************************************************/
474 ARMul_Icycles (ARMul_State * state, unsigned number, ARMword address ATTRIBUTE_UNUSED)
476 state->NumIcycles += number;
480 /***************************************************************************\
482 \***************************************************************************/
485 ARMul_Ccycles (ARMul_State * state, unsigned number, ARMword address ATTRIBUTE_UNUSED)
487 state->NumCcycles += number;
492 /* Read a byte. Do not check for alignment or access errors. */
495 ARMul_SafeReadByte (ARMul_State * state, ARMword address)
497 ARMword temp, offset;
499 temp = GetWord (state, address, FALSE);
500 offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3;
502 return (temp >> offset & 0xffL);
506 ARMul_SafeWriteByte (ARMul_State * state, ARMword address, ARMword data)
508 ARMword temp, offset;
510 temp = GetWord (state, address, FALSE);
511 offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3;
513 PutWord (state, address,
514 (temp & ~(0xffL << offset)) | ((data & 0xffL) << offset),