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