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