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