Home | History | Annotate | Line # | Download | only in arm
      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
     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
     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
    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
    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
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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
    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
    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
    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
    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
    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 
    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 
    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
    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
    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
    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
    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