This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with this program; if not, see <http://www.gnu.org/licenses/>. */
/* This file contains a complete ARMulator memory model, modelling a
"virtual memory" system. A much simpler model can be found in armfast.c,
defined to generate aborts. */
#include "armopts.h"
+#include "armos.h"
#include "armdefs.h"
+#include "ansidecl.h"
-#ifdef VALIDATE /* for running the validate suite */
-#define TUBE 48 * 1024 * 1024 /* write a char on the screen */
+#ifdef VALIDATE /* for running the validate suite */
+#define TUBE 48 * 1024 * 1024 /* write a char on the screen */
#define ABORTS 1
#endif
-#define ABORTS
+/* #define ABORTS */
-#ifdef ABORTS /* the memory system will abort */
+#ifdef ABORTS /* the memory system will abort */
/* For the old test suite Abort between 32 Kbytes and 32 Mbytes
For the new test suite Abort between 8 Mbytes and 26 Mbytes */
/* #define LOWABORT 32 * 1024
#define PAGEBITS 16
#define OFFSETBITS 0xffff
+int SWI_vector_installed = FALSE;
+
/***************************************************************************\
* Get a Word from Virtual Memory, maybe allocating the page *
\***************************************************************************/
static ARMword
-GetWord (ARMul_State * state, ARMword address)
+GetWord (ARMul_State * state, ARMword address, int check)
{
- ARMword page;
- ARMword offset;
- ARMword ** pagetable;
- ARMword * pageptr;
+ ARMword page;
+ ARMword offset;
+ ARMword **pagetable;
+ ARMword *pageptr;
+
+ if (check && state->is_XScale)
+ XScale_check_memacc (state, &address, 0);
- page = address >> PAGEBITS;
- offset = (address & OFFSETBITS) >> 2;
+ page = address >> PAGEBITS;
+ offset = (address & OFFSETBITS) >> 2;
pagetable = (ARMword **) state->MemDataPtr;
- pageptr = *(pagetable + page);
-
+ pageptr = *(pagetable + page);
+
if (pageptr == NULL)
{
pageptr = (ARMword *) malloc (PAGESIZE);
-
+
if (pageptr == NULL)
{
perror ("ARMulator can't allocate VM page");
exit (12);
}
-
+
*(pagetable + page) = pageptr;
}
-
+
return *(pageptr + offset);
}
\***************************************************************************/
static void
-PutWord (ARMul_State * state, ARMword address, ARMword data)
+PutWord (ARMul_State * state, ARMword address, ARMword data, int check)
{
- ARMword page;
- ARMword offset;
- ARMword ** pagetable;
- ARMword * pageptr;
-
- page = address >> PAGEBITS;
- offset = (address & OFFSETBITS) >> 2;
- pagetable = (ARMword **)state->MemDataPtr;
- pageptr = *(pagetable + page);
-
+ ARMword page;
+ ARMword offset;
+ ARMword **pagetable;
+ ARMword *pageptr;
+
+ if (check && state->is_XScale)
+ XScale_check_memacc (state, &address, 1);
+
+ page = address >> PAGEBITS;
+ offset = (address & OFFSETBITS) >> 2;
+ pagetable = (ARMword **) state->MemDataPtr;
+ pageptr = *(pagetable + page);
+
if (pageptr == NULL)
{
pageptr = (ARMword *) malloc (PAGESIZE);
if (pageptr == NULL)
{
perror ("ARMulator can't allocate VM page");
- exit(13);
+ exit (13);
}
-
+
*(pagetable + page) = pageptr;
}
-
+
+ if (address == 0x8)
+ SWI_vector_installed = TRUE;
+
*(pageptr + offset) = data;
}
unsigned
ARMul_MemoryInit (ARMul_State * state, unsigned long initmemsize)
{
- ARMword ** pagetable;
- unsigned page;
+ ARMword **pagetable;
+ unsigned page;
if (initmemsize)
state->MemSize = initmemsize;
-
- pagetable = (ARMword **) malloc (sizeof (ARMword) * NUMPAGES);
-
+
+ pagetable = (ARMword **) malloc (sizeof (ARMword *) * NUMPAGES);
+
if (pagetable == NULL)
return FALSE;
-
- for (page = 0 ; page < NUMPAGES ; page++)
+
+ for (page = 0; page < NUMPAGES; page++)
*(pagetable + page) = NULL;
-
- state->MemDataPtr = (unsigned char *)pagetable;
+
+ state->MemDataPtr = (unsigned char *) pagetable;
ARMul_ConsolePrint (state, ", 4 Gb memory");
-
- return TRUE;
+
+ return TRUE;
}
/***************************************************************************\
void
ARMul_MemoryExit (ARMul_State * state)
{
- ARMword page;
- ARMword ** pagetable;
- ARMword * pageptr;
+ ARMword page;
+ ARMword **pagetable;
+ ARMword *pageptr;
- pagetable = (ARMword **)state->MemDataPtr;
- for (page = 0 ; page < NUMPAGES ; page++)
+ pagetable = (ARMword **) state->MemDataPtr;
+ for (page = 0; page < NUMPAGES; page++)
{
pageptr = *(pagetable + page);
if (pageptr != NULL)
- free ((char *)pageptr);
+ free ((char *) pageptr);
}
- free ((char *)pagetable);
+ free ((char *) pagetable);
return;
}
ARMul_ReLoadInstr (ARMul_State * state, ARMword address, ARMword isize)
{
#ifdef ABORTS
- if (address >= LOWABORT && address < HIGHABORT)
+ if (address >= LOWABORT && address < HIGHABORT)
{
ARMul_PREFETCHABORT (address);
return ARMul_ABORTWORD;
}
- else
- {
- ARMul_CLEARABORT;
- }
+ else
+ {
+ ARMul_CLEARABORT;
+ }
#endif
- if ((isize == 2) && (address & 0x2))
- {
- /* We return the next two halfwords: */
- ARMword lo = GetWord (state, address);
- ARMword hi = GetWord (state, address + 4);
+ if ((isize == 2) && (address & 0x2))
+ {
+ /* We return the next two halfwords: */
+ ARMword lo = GetWord (state, address, FALSE);
+ ARMword hi = GetWord (state, address + 4, FALSE);
- if (state->bigendSig == HIGH)
- return (lo << 16) | (hi >> 16);
- else
- return ((hi & 0xFFFF) << 16) | (lo >> 16);
- }
+ if (state->bigendSig == HIGH)
+ return (lo << 16) | (hi >> 16);
+ else
+ return ((hi & 0xFFFF) << 16) | (lo >> 16);
+ }
- return GetWord (state, address);
+ return GetWord (state, address, TRUE);
}
/***************************************************************************\
* Load Instruction, Sequential Cycle *
\***************************************************************************/
-ARMword
-ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize)
+ARMword ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize)
{
- state->NumScycles ++;
+ state->NumScycles++;
#ifdef HOURGLASS
- if (( state->NumScycles & HOURGLASS_RATE ) == 0)
+ if ((state->NumScycles & HOURGLASS_RATE) == 0)
{
HOURGLASS;
}
* Load Instruction, Non Sequential Cycle *
\***************************************************************************/
-ARMword
-ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize)
+ARMword ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize)
{
- state->NumNcycles ++;
+ state->NumNcycles++;
return ARMul_ReLoadInstr (state, address, isize);
}
* Read Word (but don't tell anyone!) *
\***************************************************************************/
-ARMword
-ARMul_ReadWord (ARMul_State * state, ARMword address)
+ARMword ARMul_ReadWord (ARMul_State * state, ARMword address)
{
#ifdef ABORTS
if (address >= LOWABORT && address < HIGHABORT)
}
#endif
- return GetWord (state, address);
+ return GetWord (state, address, TRUE);
}
/***************************************************************************\
* Load Word, Sequential Cycle *
\***************************************************************************/
-ARMword
-ARMul_LoadWordS (ARMul_State * state, ARMword address)
+ARMword ARMul_LoadWordS (ARMul_State * state, ARMword address)
{
- state->NumScycles ++;
+ state->NumScycles++;
return ARMul_ReadWord (state, address);
}
* Load Word, Non Sequential Cycle *
\***************************************************************************/
-ARMword
-ARMul_LoadWordN (ARMul_State * state, ARMword address)
+ARMword ARMul_LoadWordN (ARMul_State * state, ARMword address)
{
- state->NumNcycles ++;
-
+ state->NumNcycles++;
+
return ARMul_ReadWord (state, address);
}
* Load Halfword, (Non Sequential Cycle) *
\***************************************************************************/
-ARMword
-ARMul_LoadHalfWord (ARMul_State * state, ARMword address)
+ARMword ARMul_LoadHalfWord (ARMul_State * state, ARMword address)
{
ARMword temp, offset;
- state->NumNcycles ++;
+ state->NumNcycles++;
- temp = ARMul_ReadWord (state, address);
- offset = (((ARMword)state->bigendSig * 2) ^ (address & 2)) << 3; /* bit offset into the word */
+ temp = ARMul_ReadWord (state, address);
+ offset = (((ARMword) state->bigendSig * 2) ^ (address & 2)) << 3; /* bit offset into the word */
return (temp >> offset) & 0xffff;
}
* Read Byte (but don't tell anyone!) *
\***************************************************************************/
-ARMword
-ARMul_ReadByte (ARMul_State * state, ARMword address)
+ARMword ARMul_ReadByte (ARMul_State * state, ARMword address)
{
ARMword temp, offset;
- temp = ARMul_ReadWord (state, address);
- offset = (((ARMword)state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */
+ temp = ARMul_ReadWord (state, address);
+ offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */
- return (temp >> offset & 0xffL);
+ return (temp >> offset & 0xffL);
}
/***************************************************************************\
* Load Byte, (Non Sequential Cycle) *
\***************************************************************************/
-ARMword
-ARMul_LoadByte (ARMul_State * state, ARMword address)
+ARMword ARMul_LoadByte (ARMul_State * state, ARMword address)
{
- state->NumNcycles ++;
+ state->NumNcycles++;
return ARMul_ReadByte (state, address);
}
}
#endif
- PutWord (state, address, data);
+ PutWord (state, address, data, TRUE);
}
/***************************************************************************\
void
ARMul_StoreWordS (ARMul_State * state, ARMword address, ARMword data)
{
- state->NumScycles ++;
+ state->NumScycles++;
ARMul_WriteWord (state, address, data);
}
void
ARMul_StoreWordN (ARMul_State * state, ARMword address, ARMword data)
{
- state->NumNcycles ++;
+ state->NumNcycles++;
ARMul_WriteWord (state, address, data);
}
{
ARMword temp, offset;
- state->NumNcycles ++;
-
+ state->NumNcycles++;
+
#ifdef VALIDATE
if (address == TUBE)
{
if (data == 4)
state->Emulate = FALSE;
else
- (void) putc ((char)data, stderr); /* Write Char */
+ (void) putc ((char) data, stderr); /* Write Char */
return;
}
#endif
- temp = ARMul_ReadWord (state, address);
- offset = (((ARMword)state->bigendSig * 2) ^ (address & 2)) << 3; /* bit offset into the word */
-
- PutWord (state, address, (temp & ~(0xffffL << offset)) | ((data & 0xffffL) << offset));
+ temp = ARMul_ReadWord (state, address);
+ offset = (((ARMword) state->bigendSig * 2) ^ (address & 2)) << 3; /* bit offset into the word */
+
+ PutWord (state, address,
+ (temp & ~(0xffffL << offset)) | ((data & 0xffffL) << offset),
+ TRUE);
}
/***************************************************************************\
{
ARMword temp, offset;
- temp = ARMul_ReadWord (state, address);
- offset = (((ARMword)state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */
-
- PutWord (state, address, (temp & ~(0xffL << offset)) | ((data & 0xffL) << offset));
+ temp = ARMul_ReadWord (state, address);
+ offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */
+
+ PutWord (state, address,
+ (temp & ~(0xffL << offset)) | ((data & 0xffL) << offset),
+ TRUE);
}
/***************************************************************************\
void
ARMul_StoreByte (ARMul_State * state, ARMword address, ARMword data)
{
- state->NumNcycles ++;
+ state->NumNcycles++;
#ifdef VALIDATE
if (address == TUBE)
if (data == 4)
state->Emulate = FALSE;
else
- (void) putc ((char)data,stderr); /* Write Char */
+ (void) putc ((char) data, stderr); /* Write Char */
return;
}
#endif
* Swap Word, (Two Non Sequential Cycles) *
\***************************************************************************/
-ARMword
-ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data)
+ARMword ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data)
{
ARMword temp;
- state->NumNcycles ++;
+ state->NumNcycles++;
temp = ARMul_ReadWord (state, address);
-
- state->NumNcycles ++;
-
- PutWord (state, address, data);
-
+
+ state->NumNcycles++;
+
+ PutWord (state, address, data, TRUE);
+
return temp;
}
* Swap Byte, (Two Non Sequential Cycles) *
\***************************************************************************/
-ARMword
-ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data)
+ARMword ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data)
{
ARMword temp;
temp = ARMul_LoadByte (state, address);
ARMul_StoreByte (state, address, data);
-
+
return temp;
}
\***************************************************************************/
void
-ARMul_Icycles (ARMul_State * state, unsigned number, ARMword address)
+ARMul_Icycles (ARMul_State * state, unsigned number, ARMword address ATTRIBUTE_UNUSED)
{
state->NumIcycles += number;
ARMul_CLEARABORT;
\***************************************************************************/
void
-ARMul_Ccycles (ARMul_State * state, unsigned number, ARMword address)
+ARMul_Ccycles (ARMul_State * state, unsigned number, ARMword address ATTRIBUTE_UNUSED)
{
state->NumCcycles += number;
ARMul_CLEARABORT;
}
+/* Read a byte. Do not check for alignment or access errors. */
+
+ARMword
+ARMul_SafeReadByte (ARMul_State * state, ARMword address)
+{
+ ARMword temp, offset;
+
+ temp = GetWord (state, address, FALSE);
+ offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3;
+
+ return (temp >> offset & 0xffL);
+}
+
+void
+ARMul_SafeWriteByte (ARMul_State * state, ARMword address, ARMword data)
+{
+ ARMword temp, offset;
+
+ temp = GetWord (state, address, FALSE);
+ offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3;
+ PutWord (state, address,
+ (temp & ~(0xffL << offset)) | ((data & 0xffL) << offset),
+ FALSE);
+}