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