ARM: Removed unnecessary and unused SkyEye MMU code.

Added license header back in. I originally removed this because I mostly rewrote the file, but meh
This commit is contained in:
bunnei 2014-10-07 18:56:40 -04:00
parent 3c823c0028
commit 818ba32746
22 changed files with 350 additions and 7767 deletions

View file

@ -6,19 +6,10 @@ set(SRCS
arm/dyncom/arm_dyncom_interpreter.cpp
arm/dyncom/arm_dyncom_run.cpp
arm/dyncom/arm_dyncom_thumb.cpp
arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
arm/interpreter/mmu/cache.cpp
arm/interpreter/mmu/maverick.cpp
arm/interpreter/mmu/rb.cpp
arm/interpreter/mmu/sa_mmu.cpp
arm/interpreter/mmu/tlb.cpp
arm/interpreter/mmu/wb.cpp
arm/interpreter/mmu/xscale_copro.cpp
arm/interpreter/arm_interpreter.cpp
arm/interpreter/armcopro.cpp
arm/interpreter/armemu.cpp
arm/interpreter/arminit.cpp
arm/interpreter/armmmu.cpp
arm/interpreter/armsupp.cpp
arm/interpreter/armvirt.cpp
arm/interpreter/thumbemu.cpp
@ -72,12 +63,6 @@ set(HEADERS
arm/dyncom/arm_dyncom_run.h
arm/dyncom/arm_dyncom_thumb.h
arm/interpreter/arm_interpreter.h
arm/interpreter/mmu/arm1176jzf_s_mmu.h
arm/interpreter/mmu/cache.h
arm/interpreter/mmu/rb.h
arm/interpreter/mmu/sa_mmu.h
arm/interpreter/mmu/tlb.h
arm/interpreter/mmu/wb.h
arm/skyeye_common/arm_regformat.h
arm/skyeye_common/armcpu.h
arm/skyeye_common/armdefs.h

View file

@ -27,7 +27,6 @@ ARM_DynCom::ARM_DynCom() : ticks(0) {
ARMul_SelectProcessor(state.get(), ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop);
state->lateabtSig = LOW;
mmu_init(state);
// Reset the core to initial state
ARMul_CoProInit(state.get());

View file

@ -22,7 +22,6 @@ ARM_Interpreter::ARM_Interpreter() {
ARMul_SelectProcessor(state, ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop);
state->lateabtSig = LOW;
mmu_init(state);
// Reset the core to initial state
ARMul_CoProInit(state);

View file

@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/armemu.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
@ -25,102 +24,45 @@
//chy -------
//#include "iwmmxt.h"
//chy 2005-09-19 add CP6 MRC support (for get irq number and base)
extern unsigned xscale_cp6_mrc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
//chy 2005-09-19---------------
extern unsigned xscale_cp13_init (ARMul_State * state);
extern unsigned xscale_cp13_exit (ARMul_State * state);
extern unsigned xscale_cp13_ldc (ARMul_State * state, unsigned type,
ARMword instr, ARMword data);
extern unsigned xscale_cp13_stc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
extern unsigned xscale_cp13_mrc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
extern unsigned xscale_cp13_mcr (ARMul_State * state, unsigned type,
ARMword instr, ARMword data);
extern unsigned xscale_cp13_cdp (ARMul_State * state, unsigned type,
ARMword instr);
extern unsigned xscale_cp13_read_reg (ARMul_State * state, unsigned reg,
ARMword * data);
extern unsigned xscale_cp13_write_reg (ARMul_State * state, unsigned reg,
ARMword data);
extern unsigned xscale_cp14_init (ARMul_State * state);
extern unsigned xscale_cp14_exit (ARMul_State * state);
extern unsigned xscale_cp14_ldc (ARMul_State * state, unsigned type,
ARMword instr, ARMword data);
extern unsigned xscale_cp14_stc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
extern unsigned xscale_cp14_mrc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
extern unsigned xscale_cp14_mcr (ARMul_State * state, unsigned type,
ARMword instr, ARMword data);
extern unsigned xscale_cp14_cdp (ARMul_State * state, unsigned type,
ARMword instr);
extern unsigned xscale_cp14_read_reg (ARMul_State * state, unsigned reg,
ARMword * data);
extern unsigned xscale_cp14_write_reg (ARMul_State * state, unsigned reg,
ARMword data);
extern unsigned xscale_cp15_init (ARMul_State * state);
extern unsigned xscale_cp15_exit (ARMul_State * state);
extern unsigned xscale_cp15_ldc (ARMul_State * state, unsigned type,
ARMword instr, ARMword data);
extern unsigned xscale_cp15_stc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
extern unsigned xscale_cp15_mrc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
extern unsigned xscale_cp15_mcr (ARMul_State * state, unsigned type,
ARMword instr, ARMword data);
extern unsigned xscale_cp15_cdp (ARMul_State * state, unsigned type,
ARMword instr);
extern unsigned xscale_cp15_read_reg (ARMul_State * state, unsigned reg,
ARMword * data);
extern unsigned xscale_cp15_write_reg (ARMul_State * state, unsigned reg,
ARMword data);
extern unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
unsigned cpnum);
/* Dummy Co-processors. */
static unsigned
NoCoPro3R (ARMul_State * state,
unsigned a, ARMword b)
NoCoPro3R(ARMul_State * state,
unsigned a, ARMword b)
{
return ARMul_CANT;
}
static unsigned
NoCoPro4R (ARMul_State * state,
unsigned a,
ARMword b, ARMword c)
NoCoPro4R(ARMul_State * state,
unsigned a,
ARMword b, ARMword c)
{
return ARMul_CANT;
}
static unsigned
NoCoPro4W (ARMul_State * state,
unsigned a,
ARMword b, ARMword * c)
NoCoPro4W(ARMul_State * state,
unsigned a,
ARMword b, ARMword * c)
{
return ARMul_CANT;
}
static unsigned
NoCoPro5R (ARMul_State * state,
unsigned a,
ARMword b,
ARMword c, ARMword d)
NoCoPro5R(ARMul_State * state,
unsigned a,
ARMword b,
ARMword c, ARMword d)
{
return ARMul_CANT;
}
static unsigned
NoCoPro5W (ARMul_State * state,
unsigned a,
ARMword b,
ARMword * c, ARMword * d )
NoCoPro5W(ARMul_State * state,
unsigned a,
ARMword b,
ARMword * c, ARMword * d)
{
return ARMul_CANT;
}
@ -128,55 +70,19 @@ NoCoPro5W (ARMul_State * state,
/* The XScale Co-processors. */
/* Coprocessor 15: System Control. */
static void write_cp14_reg (unsigned, ARMword);
static ARMword read_cp14_reg (unsigned);
/* There are two sets of registers for copro 15.
One set is available when opcode_2 is 0 and
the other set when opcode_2 >= 1. */
static ARMword XScale_cp15_opcode_2_is_0_Regs[16];
static ARMword XScale_cp15_opcode_2_is_not_0_Regs[16];
/* There are also a set of breakpoint registers
which are accessed via CRm instead of opcode_2. */
static ARMword XScale_cp15_DBR1;
static ARMword XScale_cp15_DBCON;
static ARMword XScale_cp15_IBCR0;
static ARMword XScale_cp15_IBCR1;
static unsigned
XScale_cp15_init (ARMul_State * state)
{
int i;
for (i = 16; i--;) {
XScale_cp15_opcode_2_is_0_Regs[i] = 0;
XScale_cp15_opcode_2_is_not_0_Regs[i] = 0;
}
/* Initialise the processor ID. */
//chy 2003-03-24, is same as cpu id in skyeye_options.c
//XScale_cp15_opcode_2_is_0_Regs[0] = 0x69052000;
XScale_cp15_opcode_2_is_0_Regs[0] = 0x69050000;
/* Initialise the cache type. */
XScale_cp15_opcode_2_is_not_0_Regs[0] = 0x0B1AA1AA;
/* Initialise the ARM Control Register. */
XScale_cp15_opcode_2_is_0_Regs[1] = 0x00000078;
return No_exp;
}
static void write_cp14_reg(unsigned, ARMword);
static ARMword read_cp14_reg(unsigned);
/* Check an access to a register. */
static unsigned
check_cp15_access (ARMul_State * state,
unsigned reg,
unsigned CRm, unsigned opcode_1, unsigned opcode_2)
check_cp15_access(ARMul_State * state,
unsigned reg,
unsigned CRm, unsigned opcode_1, unsigned opcode_2)
{
/* Do not allow access to these register in USER mode. */
//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
if (state->Mode == USER26MODE || state->Mode == USER32MODE )
if (state->Mode == USER26MODE || state->Mode == USER32MODE)
return ARMul_CANT;
/* Opcode_1should be zero. */
@ -304,440 +210,42 @@ check_cp15_access (ARMul_State * state,
return ARMul_DONE;
}
/* Coprocessor 13: Interrupt Controller and Bus Controller. */
/* There are two sets of registers for copro 13.
One set (of three registers) is available when CRm is 0
and the other set (of six registers) when CRm is 1. */
static ARMword XScale_cp13_CR0_Regs[16];
static ARMword XScale_cp13_CR1_Regs[16];
static unsigned
XScale_cp13_init (ARMul_State * state)
{
int i;
for (i = 16; i--;) {
XScale_cp13_CR0_Regs[i] = 0;
XScale_cp13_CR1_Regs[i] = 0;
}
return No_exp;
}
/* Check an access to a register. */
static unsigned
check_cp13_access (ARMul_State * state,
unsigned reg,
unsigned CRm, unsigned opcode_1, unsigned opcode_2)
{
/* Do not allow access to these registers in USER mode. */
//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
if (state->Mode == USER26MODE || state->Mode == USER32MODE )
return ARMul_CANT;
/* The opcodes should be zero. */
if ((opcode_1 != 0) || (opcode_2 != 0))
return ARMul_CANT;
/* Do not allow access to these register if bit
13 of coprocessor 15's register 15 is zero. */
if (!CP_ACCESS_ALLOWED (state, 13))
return ARMul_CANT;
/* Registers 0, 4 and 8 are defined when CRm == 0.
Registers 0, 1, 4, 5, 6, 7, 8 are defined when CRm == 1.
For all other CRm values undefined behaviour results. */
if (CRm == 0) {
if (reg == 0 || reg == 4 || reg == 8)
return ARMul_DONE;
}
else if (CRm == 1) {
if (reg == 0 || reg == 1 || (reg >= 4 && reg <= 8))
return ARMul_DONE;
}
return ARMul_CANT;
}
/* Coprocessor 14: Performance Monitoring, Clock and Power management,
Software Debug. */
static ARMword XScale_cp14_Regs[16];
static unsigned
XScale_cp14_init (ARMul_State * state)
{
int i;
for (i = 16; i--;)
XScale_cp14_Regs[i] = 0;
return No_exp;
}
/* Check an access to a register. */
static unsigned
check_cp14_access (ARMul_State * state,
unsigned reg,
unsigned CRm, unsigned opcode1, unsigned opcode2)
{
/* Not allowed to access these register in USER mode. */
//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
if (state->Mode == USER26MODE || state->Mode == USER32MODE )
return ARMul_CANT;
/* CRm should be zero. */
if (CRm != 0)
return ARMul_CANT;
/* OPcodes should be zero. */
if (opcode1 != 0 || opcode2 != 0)
return ARMul_CANT;
/* Accessing registers 4 or 5 has unpredicatable results. */
if (reg >= 4 && reg <= 5)
return ARMul_CANT;
return ARMul_DONE;
}
/* Here's ARMulator's MMU definition. A few things to note:
1) It has eight registers, but only two are defined.
2) You can only access its registers with MCR and MRC.
3) MMU Register 0 (ID) returns 0x41440110
4) Register 1 only has 4 bits defined. Bits 0 to 3 are unused, bit 4
controls 32/26 bit program space, bit 5 controls 32/26 bit data space,
bit 6 controls late abort timimg and bit 7 controls big/little endian. */
static ARMword MMUReg[8];
static unsigned
MMUInit (ARMul_State * state)
{
/* 2004-05-09 chy
-------------------------------------------------------------
read ARM Architecture Reference Manual
2.6.5 Data Abort
There are three Abort Model in ARM arch.
Early Abort Model: used in some ARMv3 and earlier implementations. In this
model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and
the base register was unchanged for all other instructions. (oldest)
Base Restored Abort Model: If a Data Abort occurs in an instruction which
specifies base register writeback, the value in the base register is
unchanged. (strongarm, xscale)
Base Updated Abort Model: If a Data Abort occurs in an instruction which
specifies base register writeback, the base register writeback still occurs.
(arm720T)
read PART B
chap2 The System Control Coprocessor CP15
2.4 Register1:control register
L(bit 6): in some ARMv3 and earlier implementations, the abort model of the
processor could be configured:
0=early Abort Model Selected(now obsolete)
1=Late Abort Model selceted(same as Base Updated Abort Model)
on later processors, this bit reads as 1 and ignores writes.
-------------------------------------------------------------
So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
if lateabtSig=0, then it means Base Restored Abort Model
because the ARMs which skyeye simulates are all belonged to ARMv4,
so I think MMUReg[1]'s bit 6 should always be 1
*/
MMUReg[1] = state->prog32Sig << 4 |
state->data32Sig << 5 | 1 << 6 | state->bigendSig << 7;
//state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7;
NOTICE_LOG(ARM11, "ARMul_ConsolePrint: MMU present");
return TRUE;
}
static unsigned
MMUMRC (ARMul_State * state, unsigned type,
ARMword instr, ARMword * value)
{
mmu_mrc (state, instr, value);
return (ARMul_DONE);
}
static unsigned
MMUMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
{
mmu_mcr (state, instr, value);
return (ARMul_DONE);
}
/* What follows is the Validation Suite Coprocessor. It uses two
co-processor numbers (4 and 5) and has the follwing functionality.
Sixteen registers. Both co-processor nuimbers can be used in an MCR
and MRC to access these registers. CP 4 can LDC and STC to and from
the registers. CP 4 and CP 5 CDP 0 will busy wait for the number of
cycles specified by a CP register. CP 5 CDP 1 issues a FIQ after a
number of cycles (specified in a CP register), CDP 2 issues an IRQW
in the same way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5
stores a 32 bit time value in a CP register (actually it's the total
number of N, S, I, C and F cyles). */
static ARMword ValReg[16];
static unsigned
ValLDC (ARMul_State * state,
unsigned type, ARMword instr, ARMword data)
{
static unsigned words;
if (type != ARMul_DATA)
words = 0;
else {
ValReg[BITS (12, 15)] = data;
if (BIT (22))
/* It's a long access, get two words. */
if (words++ != 4)
return ARMul_INC;
}
return ARMul_DONE;
}
static unsigned
ValSTC (ARMul_State * state,
unsigned type, ARMword instr, ARMword * data)
{
static unsigned words;
if (type != ARMul_DATA)
words = 0;
else {
*data = ValReg[BITS (12, 15)];
if (BIT (22))
/* It's a long access, get two words. */
if (words++ != 4)
return ARMul_INC;
}
return ARMul_DONE;
}
static unsigned
ValMRC (ARMul_State * state,
unsigned type, ARMword instr, ARMword * value)
{
*value = ValReg[BITS (16, 19)];
return ARMul_DONE;
}
static unsigned
ValMCR (ARMul_State * state,
unsigned type, ARMword instr, ARMword value)
{
ValReg[BITS (16, 19)] = value;
return ARMul_DONE;
}
static unsigned
ValCDP (ARMul_State * state, unsigned type, ARMword instr)
{
static unsigned int finish = 0;
if (BITS (20, 23) != 0)
return ARMul_CANT;
if (type == ARMul_FIRST) {
ARMword howlong;
howlong = ValReg[BITS (0, 3)];
/* First cycle of a busy wait. */
finish = ARMul_Time (state) + howlong;
return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
}
else if (type == ARMul_BUSY) {
if (ARMul_Time (state) >= finish)
return ARMul_DONE;
else
return ARMul_BUSY;
}
return ARMul_CANT;
}
static unsigned
DoAFIQ (ARMul_State * state)
{
state->NfiqSig = LOW;
return 0;
}
static unsigned
DoAIRQ (ARMul_State * state)
{
state->NirqSig = LOW;
return 0;
}
static unsigned
IntCDP (ARMul_State * state, unsigned type, ARMword instr)
{
static unsigned int finish;
ARMword howlong;
howlong = ValReg[BITS (0, 3)];
switch ((int) BITS (20, 23)) {
case 0:
if (type == ARMul_FIRST) {
/* First cycle of a busy wait. */
finish = ARMul_Time (state) + howlong;
return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
}
else if (type == ARMul_BUSY) {
if (ARMul_Time (state) >= finish)
return ARMul_DONE;
else
return ARMul_BUSY;
}
return ARMul_DONE;
case 1:
if (howlong == 0)
ARMul_Abort (state, ARMul_FIQV);
else
ARMul_ScheduleEvent (state, howlong, DoAFIQ);
return ARMul_DONE;
case 2:
if (howlong == 0)
ARMul_Abort (state, ARMul_IRQV);
else
ARMul_ScheduleEvent (state, howlong, DoAIRQ);
return ARMul_DONE;
case 3:
state->NfiqSig = HIGH;
return ARMul_DONE;
case 4:
state->NirqSig = HIGH;
return ARMul_DONE;
case 5:
ValReg[BITS (0, 3)] = ARMul_Time (state);
return ARMul_DONE;
}
return ARMul_CANT;
}
/* Install co-processor instruction handlers in this routine. */
unsigned
ARMul_CoProInit (ARMul_State * state)
ARMul_CoProInit(ARMul_State * state)
{
unsigned int i;
/* Initialise tham all first. */
for (i = 0; i < 16; i++)
ARMul_CoProDetach (state, i);
ARMul_CoProDetach(state, i);
/* Install CoPro Instruction handlers here.
The format is:
ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
LDC routine, STC routine, MRC routine, MCR routine,
CDP routine, Read Reg routine, Write Reg routine). */
if (state->is_ep9312) {
ARMul_CoProAttach (state, 4, NULL, NULL, DSPLDC4, DSPSTC4,
DSPMRC4, DSPMCR4, NULL, NULL, DSPCDP4, NULL, NULL);
ARMul_CoProAttach (state, 5, NULL, NULL, DSPLDC5, DSPSTC5,
DSPMRC5, DSPMCR5, NULL, NULL, DSPCDP5, NULL, NULL);
ARMul_CoProAttach (state, 6, NULL, NULL, NULL, NULL,
DSPMRC6, DSPMCR6, NULL, NULL, DSPCDP6, NULL, NULL);
}
else {
ARMul_CoProAttach (state, 4, NULL, NULL, ValLDC, ValSTC,
ValMRC, ValMCR, NULL, NULL, ValCDP, NULL, NULL);
ARMul_CoProAttach (state, 5, NULL, NULL, NULL, NULL,
ValMRC, ValMCR, NULL, NULL, IntCDP, NULL, NULL);
}
if (state->is_XScale) {
//chy 2005-09-19, for PXA27x's CP6
if (state->is_pxa27x) {
ARMul_CoProAttach (state, 6, NULL, NULL,
NULL, NULL, xscale_cp6_mrc,
NULL, NULL, NULL, NULL, NULL, NULL);
}
//chy 2005-09-19 end-------------
ARMul_CoProAttach (state, 13, xscale_cp13_init,
xscale_cp13_exit, xscale_cp13_ldc,
xscale_cp13_stc, xscale_cp13_mrc,
xscale_cp13_mcr, NULL, NULL, xscale_cp13_cdp,
xscale_cp13_read_reg,
xscale_cp13_write_reg);
ARMul_CoProAttach (state, 14, xscale_cp14_init,
xscale_cp14_exit, xscale_cp14_ldc,
xscale_cp14_stc, xscale_cp14_mrc,
xscale_cp14_mcr, NULL, NULL, xscale_cp14_cdp,
xscale_cp14_read_reg,
xscale_cp14_write_reg);
//chy: 2003-08-24.
ARMul_CoProAttach (state, 15, xscale_cp15_init,
xscale_cp15_exit, xscale_cp15_ldc,
xscale_cp15_stc, xscale_cp15_mrc,
xscale_cp15_mcr, NULL, NULL, xscale_cp15_cdp,
xscale_cp15_read_reg,
xscale_cp15_write_reg);
}
else if (state->is_v6) {
ARMul_CoProAttach (state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
if (state->is_v6) {
ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
ARMul_CoProAttach (state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
ARMul_CoProAttach(state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);
/*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);*/
}
else { //all except xscale
ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
// MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);
}
//chy 2003-09-03 do it in future!!!!????
//chy 2003-09-03 do it in future!!!!????
#if 0
if (state->is_iWMMXt) {
ARMul_CoProAttach (state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC,
ARMul_CoProAttach(state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC,
NULL, NULL, IwmmxtCDP, NULL, NULL);
ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL,
ARMul_CoProAttach(state, 1, NULL, NULL, NULL, NULL,
IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL,
NULL);
}
#endif
//-----------------------------------------------------------------------------
//chy 2004-05-25, found the user/system code visit CP 1,2, so I add below code.
ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL,
ValMRC, ValMCR, NULL, NULL, NULL, NULL, NULL);
ARMul_CoProAttach (state, 2, NULL, NULL, ValLDC, ValSTC,
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
//------------------------------------------------------------------------------
/* No handlers below here. */
/* Call all the initialisation routines. */
@ -751,7 +259,7 @@ ARMul_CoProInit (ARMul_State * state)
/* Install co-processor finalisation routines in this routine. */
void
ARMul_CoProExit (ARMul_State * state)
ARMul_CoProExit(ARMul_State * state)
{
register unsigned i;
@ -760,24 +268,24 @@ ARMul_CoProExit (ARMul_State * state)
(state->CPExit[i]) (state);
for (i = 0; i < 16; i++) /* Detach all handlers. */
ARMul_CoProDetach (state, i);
ARMul_CoProDetach(state, i);
}
/* Routines to hook Co-processors into ARMulator. */
void
ARMul_CoProAttach (ARMul_State * state,
unsigned number,
ARMul_CPInits * init,
ARMul_CPExits * exit,
ARMul_LDCs * ldc,
ARMul_STCs * stc,
ARMul_MRCs * mrc,
ARMul_MCRs * mcr,
ARMul_MRRCs * mrrc,
ARMul_MCRRs * mcrr,
ARMul_CDPs * cdp,
ARMul_CPReads * read, ARMul_CPWrites * write)
ARMul_CoProAttach(ARMul_State * state,
unsigned number,
ARMul_CPInits * init,
ARMul_CPExits * exit,
ARMul_LDCs * ldc,
ARMul_STCs * stc,
ARMul_MRCs * mrc,
ARMul_MCRs * mcr,
ARMul_MRRCs * mrrc,
ARMul_MCRRs * mcrr,
ARMul_CDPs * cdp,
ARMul_CPReads * read, ARMul_CPWrites * write)
{
if (init != NULL)
state->CPInit[number] = init;
@ -804,9 +312,9 @@ ARMul_CoProAttach (ARMul_State * state,
}
void
ARMul_CoProDetach (ARMul_State * state, unsigned number)
ARMul_CoProDetach(ARMul_State * state, unsigned number)
{
ARMul_CoProAttach (state, number, NULL, NULL,
ARMul_CoProAttach(state, number, NULL, NULL,
NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
NoCoPro5W, NoCoPro5R, NoCoPro3R, NULL, NULL);
@ -815,27 +323,3 @@ ARMul_CoProDetach (ARMul_State * state, unsigned number)
state->CPRead[number] = NULL;
state->CPWrite[number] = NULL;
}
//chy 2003-09-03:below funs just replace the old ones
/* Set the XScale FSR and FAR registers. */
void
XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword _far)
{
//if (!state->is_XScale || (read_cp14_reg (10) & (1UL << 31)) == 0)
if (!state->is_XScale)
return;
//assume opcode2=0 crm =0
xscale_cp15_write_reg (state, 5, fsr);
xscale_cp15_write_reg (state, 6, _far);
}
//chy 2003-09-03 seems 0 is CANT, 1 is DONE ????
int
XScale_debug_moe (ARMul_State * state, int moe)
{
//chy 2003-09-03 , W/R CP14 reg, now it's no use ????
printf ("SKYEYE: XScale_debug_moe called !!!!\n");
return 1;
}

View file

@ -1,238 +0,0 @@
/*
armmmu.c - Memory Management Unit emulation.
ARMulator extensions for the ARM7100 family.
Copyright (C) 1999 Ben Williamson
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
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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
*/
#include <assert.h>
#include <string.h>
#include "core/arm/skyeye_common/armdefs.h"
/* two header for arm disassemble */
//#include "skyeye_arch.h"
#include "core/arm/skyeye_common/armcpu.h"
extern mmu_ops_t xscale_mmu_ops;
exception_t arm_mmu_write(short size, u32 addr, uint32_t *value);
exception_t arm_mmu_read(short size, u32 addr, uint32_t *value);
#define MMU_OPS (state->mmu.ops)
ARMword skyeye_cachetype = -1;
int
mmu_init (ARMul_State * state)
{
int ret;
state->mmu.control = 0x70;
state->mmu.translation_table_base = 0xDEADC0DE;
state->mmu.domain_access_control = 0xDEADC0DE;
state->mmu.fault_status = 0;
state->mmu.fault_address = 0;
state->mmu.process_id = 0;
switch (state->cpu->cpu_val & state->cpu->cpu_mask) {
//case SA1100:
//case SA1110:
// NOTICE_LOG(ARM11, "SKYEYE: use sa11xx mmu ops\n");
// state->mmu.ops = sa_mmu_ops;
// break;
//case PXA250:
//case PXA270: //xscale
// NOTICE_LOG(ARM11, "SKYEYE: use xscale mmu ops\n");
// state->mmu.ops = xscale_mmu_ops;
// break;
//case 0x41807200: //arm720t
//case 0x41007700: //arm7tdmi
//case 0x41007100: //arm7100
// NOTICE_LOG(ARM11, "SKYEYE: use arm7100 mmu ops\n");
// state->mmu.ops = arm7100_mmu_ops;
// break;
//case 0x41009200:
// NOTICE_LOG(ARM11, "SKYEYE: use arm920t mmu ops\n");
// state->mmu.ops = arm920t_mmu_ops;
// break;
//case 0x41069260:
// NOTICE_LOG(ARM11, "SKYEYE: use arm926ejs mmu ops\n");
// state->mmu.ops = arm926ejs_mmu_ops;
// break;
/* case 0x560f5810: */
case 0x0007b000:
NOTICE_LOG(ARM11, "SKYEYE: use arm11jzf-s mmu ops\n");
state->mmu.ops = arm1176jzf_s_mmu_ops;
break;
default:
ERROR_LOG (ARM11,
"SKYEYE: armmmu.c : mmu_init: unknown cpu_val&cpu_mask 0x%x\n",
state->cpu->cpu_val & state->cpu->cpu_mask);
break;
};
ret = state->mmu.ops.init (state);
state->mmu_inited = (ret == 0);
/* initialize mmu_read and mmu_write for disassemble */
//skyeye_config_t *config = get_current_config();
//generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name);
//arch_instance->mmu_read = arm_mmu_read;
//arch_instance->mmu_write = arm_mmu_write;
return ret;
}
int
mmu_reset (ARMul_State * state)
{
if (state->mmu_inited)
mmu_exit (state);
return mmu_init (state);
}
void
mmu_exit (ARMul_State * state)
{
MMU_OPS.exit (state);
state->mmu_inited = 0;
}
fault_t
mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
return MMU_OPS.read_byte (state, virt_addr, data);
};
fault_t
mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
return MMU_OPS.read_halfword (state, virt_addr, data);
};
fault_t
mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
return MMU_OPS.read_word (state, virt_addr, data);
};
fault_t
mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data)
{
fault_t fault;
//static int count = 0;
//count ++;
fault = MMU_OPS.write_byte (state, virt_addr, data);
return fault;
}
fault_t
mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data)
{
fault_t fault;
//static int count = 0;
//count ++;
fault = MMU_OPS.write_halfword (state, virt_addr, data);
return fault;
}
fault_t
mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data)
{
fault_t fault;
fault = MMU_OPS.write_word (state, virt_addr, data);
/*used for debug for MMU*
if (!fault){
ARMword tmp;
if (mmu_read_word(state, virt_addr, &tmp)){
err_msg("load back\n");
exit(-1);
}else{
if (tmp != data){
err_msg("load back not equal %d %x\n", count, virt_addr);
}
}
}
*/
return fault;
};
fault_t
mmu_load_instr (ARMul_State * state, ARMword virt_addr, ARMword * instr)
{
return MMU_OPS.load_instr (state, virt_addr, instr);
}
ARMword
mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
{
return MMU_OPS.mrc (state, instr, value);
}
void
mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
{
MMU_OPS.mcr (state, instr, value);
}
/*ywc 20050416*/
int
mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr)
{
return (MMU_OPS.v2p_dbct (state, virt_addr, phys_addr));
}
//
//
///* dis_mmu_read for disassemble */
//exception_t arm_mmu_read(short size, uint32_t addr, uint32_t * value)
//{
// ARMul_State *state;
// ARM_CPU_State *cpu = get_current_cpu();
// state = &cpu->core[0];
// switch(size){
// case 8:
// MMU_OPS.read_byte (state, addr, value);
// break;
// case 16:
// case 32:
// break;
// default:
// ERROR_LOG(ARM11, "Error size %d", size);
// break;
// }
// return No_exp;
//}
///* dis_mmu_write for disassemble */
//exception_t arm_mmu_write(short size, uint32_t addr, uint32_t *value)
//{
// ARMul_State *state;
// ARM_CPU_State *cpu = get_current_cpu();
// state = &cpu->core[0];
// switch(size){
// case 8:
// MMU_OPS.write_byte (state, addr, value);
// break;
// case 16:
// case 32:
// break;
// default:
// printf("In %s error size %d Line %d\n", __func__, size, __LINE__);
// break;
// }
// return No_exp;
//}

View file

@ -24,311 +24,34 @@ freed as they might be needed again. A single area of memory may be
defined to generate aborts. */
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/skyeye_defs.h"
//#include "code_cov.h"
#include "core/arm/skyeye_common/armemu.h"
#ifdef VALIDATE /* for running the validate suite */
#define TUBE 48 * 1024 * 1024 /* write a char on the screen */
#define ABORTS 1
#endif
#include "core/mem_map.h"
/* #define ABORTS */
#define dumpstack 1
#define dumpstacksize 0x10
#define maxdmupaddr 0x0033a850
#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 HIGHABORT 32 * 1024 * 1024 */
#define LOWABORT 8 * 1024 * 1024
#define HIGHABORT 26 * 1024 * 1024
/*ARMword ARMul_GetCPSR (ARMul_State * state) {
return 0;
}
ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode) {
return 0;
}
void ARMul_SetCPSR (ARMul_State * state, ARMword value) {
#endif
}
void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) {
#define NUMPAGES 64 * 1024
#define PAGESIZE 64 * 1024
#define PAGEBITS 16
#define OFFSETBITS 0xffff
//chy 2003-08-19: seems no use ????
int SWI_vector_installed = FALSE;
extern ARMword skyeye_cachetype;
}*/
/***************************************************************************\
* Get a byte into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
GetByte (ARMul_State * state, ARMword address, ARMword * data)
{
fault_t fault;
fault = mmu_read_byte (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
// printf("SKYEYE: GetByte fault %d \n", fault);
}
return fault;
void ARMul_Icycles(ARMul_State * state, unsigned number, ARMword address) {
}
/***************************************************************************\
* Get a halfword into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
GetHalfWord (ARMul_State * state, ARMword address, ARMword * data)
{
fault_t fault;
fault = mmu_read_halfword (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
// printf("SKYEYE: GetHalfWord fault %d \n", fault);
}
return fault;
void ARMul_Ccycles(ARMul_State * state, unsigned number, ARMword address) {
}
/***************************************************************************\
* Get a Word from Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
GetWord (ARMul_State * state, ARMword address, ARMword * data)
{
fault_t fault;
fault = mmu_read_word (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
#if 0
/* XXX */ extern int hack;
hack = 1;
#endif
#if 0
printf ("mmu_read_word at 0x%08x: ", address);
switch (fault) {
case ALIGNMENT_FAULT:
printf ("ALIGNMENT_FAULT");
break;
case SECTION_TRANSLATION_FAULT:
printf ("SECTION_TRANSLATION_FAULT");
break;
case PAGE_TRANSLATION_FAULT:
printf ("PAGE_TRANSLATION_FAULT");
break;
case SECTION_DOMAIN_FAULT:
printf ("SECTION_DOMAIN_FAULT");
break;
case SECTION_PERMISSION_FAULT:
printf ("SECTION_PERMISSION_FAULT");
break;
case SUBPAGE_PERMISSION_FAULT:
printf ("SUBPAGE_PERMISSION_FAULT");
break;
default:
printf ("Unrecognized fault number!");
}
printf ("\tpc = 0x%08x\n", state->Reg[15]);
#endif
}
return fault;
}
//2003-07-10 chy: lyh change
/****************************************************************************\
* Load a Instrion Word into Virtual Memory *
\****************************************************************************/
static fault_t
LoadInstr (ARMul_State * state, ARMword address, ARMword * instr)
{
fault_t fault;
fault = mmu_load_instr (state, address, instr);
return fault;
//if (fault)
// log_msg("load_instr fault = %d, address = %x\n", fault, address);
}
/***************************************************************************\
* Put a byte into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
PutByte (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = mmu_write_byte (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
// printf("SKYEYE: PutByte fault %d \n", fault);
}
return fault;
}
/***************************************************************************\
* Put a halfword into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
PutHalfWord (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = mmu_write_halfword (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
// printf("SKYEYE: PutHalfWord fault %d \n", fault);
}
return fault;
}
/***************************************************************************\
* Put a Word into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
PutWord (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = mmu_write_word (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
#if 0
/* XXX */ extern int hack;
hack = 1;
#endif
#if 0
printf ("mmu_write_word at 0x%08x: ", address);
switch (fault) {
case ALIGNMENT_FAULT:
printf ("ALIGNMENT_FAULT");
break;
case SECTION_TRANSLATION_FAULT:
printf ("SECTION_TRANSLATION_FAULT");
break;
case PAGE_TRANSLATION_FAULT:
printf ("PAGE_TRANSLATION_FAULT");
break;
case SECTION_DOMAIN_FAULT:
printf ("SECTION_DOMAIN_FAULT");
break;
case SECTION_PERMISSION_FAULT:
printf ("SECTION_PERMISSION_FAULT");
break;
case SUBPAGE_PERMISSION_FAULT:
printf ("SUBPAGE_PERMISSION_FAULT");
break;
default:
printf ("Unrecognized fault number!");
}
printf ("\tpc = 0x%08x\n", state->Reg[15]);
#endif
}
return fault;
}
/***************************************************************************\
* Initialise the memory interface *
\***************************************************************************/
unsigned
ARMul_MemoryInit (ARMul_State * state, unsigned int initmemsize)
{
return TRUE;
}
/***************************************************************************\
* Remove the memory interface *
\***************************************************************************/
void
ARMul_MemoryExit (ARMul_State * state)
{
}
/***************************************************************************\
* ReLoad Instruction *
\***************************************************************************/
ARMword
ARMul_ReLoadInstr (ARMul_State * state, ARMword address, ARMword isize)
{
ARMword data;
fault_t fault;
#ifdef ABORTS
if (address >= LOWABORT && address < HIGHABORT) {
ARMul_PREFETCHABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
#endif
#if 0
/* do profiling for code coverage */
if (skyeye_config.code_cov.prof_on)
cov_prof(EXEC_FLAG, address);
#endif
#if 1
if ((isize == 2) && (address & 0x2)) {
ARMword lo, hi;
if (!(skyeye_cachetype == INSTCACHE))
fault = GetHalfWord (state, address, &lo);
else
fault = LoadInstr (state, address, &lo);
#if 0
if (!fault) {
if (!(skyeye_cachetype == INSTCACHE))
fault = GetHalfWord (state, address + isize, &hi);
else
fault = LoadInstr (state, address + isize, &hi);
}
#endif
if (fault) {
ARMul_PREFETCHABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return lo;
#if 0
if (state->bigendSig == HIGH)
return (lo << 16) | (hi >> 16);
else
return ((hi & 0xFFFF) << 16) | (lo >> 16);
#endif
}
#endif
if (!(skyeye_cachetype == INSTCACHE))
fault = GetWord (state, address, &data);
else
fault = LoadInstr (state, address, &data);
if (fault) {
/* dyf add for s3c6410 no instcache temporary 2010.9.17 */
if (!(skyeye_cachetype == INSTCACHE)) {
/* set translation fault on prefetch abort */
state->mmu.fault_statusi = fault & 0xFF;
state->mmu.fault_address = address;
}
/* add end */
ARMul_PREFETCHABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return data;
}
/***************************************************************************\
* 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++;
#ifdef HOURGLASS
@ -336,345 +59,107 @@ ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize)
HOURGLASS;
}
#endif
return ARMul_ReLoadInstr (state, address, isize);
}
/***************************************************************************\
* Load Instruction, Non Sequential Cycle *
\***************************************************************************/
ARMword
ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize)
{
state->NumNcycles++;
return ARMul_ReLoadInstr (state, address, isize);
}
/***************************************************************************\
* Read Word (but don't tell anyone!) *
\***************************************************************************/
ARMword
ARMul_ReadWord (ARMul_State * state, ARMword address)
{
ARMword data;
fault_t fault;
#ifdef ABORTS
if (address >= LOWABORT && address < HIGHABORT) {
ARMul_DATAABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
#endif
fault = GetWord (state, address, &data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return data;
}
/***************************************************************************\
* Load Word, Sequential Cycle *
\***************************************************************************/
ARMword
ARMul_LoadWordS (ARMul_State * state, ARMword address)
{
state->NumScycles++;
return ARMul_ReadWord (state, address);
}
/***************************************************************************\
* Load Word, Non Sequential Cycle *
\***************************************************************************/
ARMword
ARMul_LoadWordN (ARMul_State * state, ARMword address)
{
state->NumNcycles++;
return ARMul_ReadWord (state, address);
}
/***************************************************************************\
* Load Halfword, (Non Sequential Cycle) *
\***************************************************************************/
ARMword
ARMul_LoadHalfWord (ARMul_State * state, ARMword address)
{
ARMword data;
fault_t fault;
state->NumNcycles++;
fault = GetHalfWord (state, address, &data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return data;
}
/***************************************************************************\
* Read Byte (but don't tell anyone!) *
\***************************************************************************/
int ARMul_ICE_ReadByte(ARMul_State * state, ARMword address, ARMword *presult)
{
ARMword data;
fault_t fault;
fault = GetByte (state, address, &data);
if (fault) {
*presult=-1; fault=ALIGNMENT_FAULT; return fault;
}else{
*(char *)presult=(unsigned char)(data & 0xff); fault=NO_FAULT; return fault;
}
}
ARMword
ARMul_ReadByte (ARMul_State * state, ARMword address)
{
ARMword data;
fault_t fault;
fault = GetByte (state, address, &data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return data;
}
/***************************************************************************\
* Load Byte, (Non Sequential Cycle) *
\***************************************************************************/
ARMword
ARMul_LoadByte (ARMul_State * state, ARMword address)
{
state->NumNcycles++;
return ARMul_ReadByte (state, address);
}
/***************************************************************************\
* Write Word (but don't tell anyone!) *
\***************************************************************************/
void
ARMul_WriteWord (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
#ifdef ABORTS
if (address >= LOWABORT && address < HIGHABORT) {
ARMul_DATAABORT (address);
return;
}
else {
ARMul_CLEARABORT;
}
#endif
fault = PutWord (state, address, data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return;
}
else {
ARMul_CLEARABORT;
}
}
/***************************************************************************\
* Store Word, Sequential Cycle *
\***************************************************************************/
void
ARMul_StoreWordS (ARMul_State * state, ARMword address, ARMword data)
{
state->NumScycles++;
ARMul_WriteWord (state, address, data);
}
/***************************************************************************\
* Store Word, Non Sequential Cycle *
\***************************************************************************/
void
ARMul_StoreWordN (ARMul_State * state, ARMword address, ARMword data)
{
state->NumNcycles++;
ARMul_WriteWord (state, address, data);
}
/***************************************************************************\
* Store HalfWord, (Non Sequential Cycle) *
\***************************************************************************/
void
ARMul_StoreHalfWord (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
state->NumNcycles++;
fault = PutHalfWord (state, address, data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return;
}
else {
ARMul_CLEARABORT;
}
}
//chy 2006-04-15
int ARMul_ICE_WriteByte (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = PutByte (state, address, data);
if (fault)
return 1;
if (isize == 2)
return (u16)Memory::Read16(address);
else
return 0;
}
/***************************************************************************\
* Write Byte (but don't tell anyone!) *
\***************************************************************************/
//chy 2003-07-10, add real write byte fun
void
ARMul_WriteByte (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = PutByte (state, address, data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return;
}
else {
ARMul_CLEARABORT;
}
return (u32)Memory::Read32(address);
}
/***************************************************************************\
* Store Byte, (Non Sequential Cycle) *
\***************************************************************************/
void
ARMul_StoreByte (ARMul_State * state, ARMword address, ARMword data)
{
ARMword ARMul_LoadInstrN(ARMul_State * state, ARMword address, ARMword isize) {
state->NumNcycles++;
#ifdef VALIDATE
if (address == TUBE) {
if (data == 4)
state->Emulate = FALSE;
if (isize == 2)
return (u16)Memory::Read16(address);
else
(void) putc ((char) data, stderr); /* Write Char */
return;
}
#endif
ARMul_WriteByte (state, address, data);
return (u32)Memory::Read32(address);
}
/***************************************************************************\
* Swap Word, (Two Non Sequential Cycles) *
\***************************************************************************/
ARMword ARMul_ReLoadInstr(ARMul_State * state, ARMword address, ARMword isize) {
ARMword data;
ARMword
ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data)
{
if ((isize == 2) && (address & 0x2)) {
ARMword lo;
lo = (u16)Memory::Read16(address);
return lo;
}
data = (u32)Memory::Read32(address);
return data;
}
ARMword ARMul_ReadWord(ARMul_State * state, ARMword address) {
ARMword data;
data = Memory::Read32(address);
return data;
}
ARMword ARMul_LoadWordS(ARMul_State * state, ARMword address) {
state->NumScycles++;
return ARMul_ReadWord(state, address);
}
ARMword ARMul_LoadWordN(ARMul_State * state, ARMword address) {
state->NumNcycles++;
return ARMul_ReadWord(state, address);
}
ARMword ARMul_LoadHalfWord(ARMul_State * state, ARMword address) {
state->NumNcycles++;
return (u16)Memory::Read16(address);;
}
ARMword ARMul_ReadByte(ARMul_State * state, ARMword address) {
return (u8)Memory::Read8(address);
}
ARMword ARMul_LoadByte(ARMul_State * state, ARMword address) {
state->NumNcycles++;
return ARMul_ReadByte(state, address);
}
void ARMul_StoreHalfWord(ARMul_State * state, ARMword address, ARMword data) {
state->NumNcycles++;
Memory::Write16(address, data);
}
void ARMul_StoreByte(ARMul_State * state, ARMword address, ARMword data) {
state->NumNcycles++;
ARMul_WriteByte(state, address, data);
}
ARMword ARMul_SwapWord(ARMul_State * state, ARMword address, ARMword data) {
ARMword temp;
state->NumNcycles++;
temp = ARMul_ReadWord (state, address);
temp = ARMul_ReadWord(state, address);
state->NumNcycles++;
PutWord (state, address, data);
Memory::Write32(address, data);
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);
temp = ARMul_LoadByte(state, address);
Memory::Write8(address, data);
return temp;
}
/***************************************************************************\
* Count I Cycles *
\***************************************************************************/
void
ARMul_Icycles (ARMul_State * state, unsigned number,
ARMword address)
{
state->NumIcycles += number;
ARMul_CLEARABORT;
void ARMul_WriteWord(ARMul_State * state, ARMword address, ARMword data) {
Memory::Write32(address, data);
}
/***************************************************************************\
* Count C Cycles *
\***************************************************************************/
void
ARMul_Ccycles (ARMul_State * state, unsigned number,
ARMword address)
void ARMul_WriteByte(ARMul_State * state, ARMword address, ARMword data)
{
state->NumCcycles += number;
ARMul_CLEARABORT;
Memory::Write8(address, data);
}
void ARMul_StoreWordS(ARMul_State * state, ARMword address, ARMword data)
{
state->NumScycles++;
ARMul_WriteWord(state, address, data);
}
void ARMul_StoreWordN(ARMul_State * state, ARMword address, ARMword data)
{
state->NumNcycles++;
ARMul_WriteWord(state, address, data);
}

File diff suppressed because it is too large Load diff

View file

@ -1,37 +0,0 @@
/*
arm1176JZF-S_mmu.h - ARM1176JZF-S Memory Management Unit emulation.
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
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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
*/
#ifndef _ARM1176JZF_S_MMU_H_
#define _ARM1176JZF_S_MMU_H_
#if 0
typedef struct arm1176jzf-s_mmu_s
{
tlb_t i_tlb;
cache_t i_cache;
tlb_t d_tlb;
cache_t d_cache;
wb_t wb_t;
} arm1176jzf-s_mmu_t;
#endif
extern mmu_ops_t arm1176jzf_s_mmu_ops;
ARMword
arm1176jzf_s_mmu_mrc (ARMul_State *state, ARMword instr, ARMword *value);
#endif /*_ARM1176JZF_S_MMU_H_*/

View file

@ -1,370 +0,0 @@
#include "core/arm/skyeye_common/armdefs.h"
/* mmu cache init
*
* @cache_t :cache_t to init
* @width :cache line width in byte
* @way :way of each cache set
* @set :cache set num
*
* $ -1: error
* 0: sucess
*/
int
mmu_cache_init (cache_s * cache_t, int width, int way, int set, int w_mode)
{
int i, j;
cache_set_t *sets;
cache_line_t *lines;
/*alloc cache set */
sets = NULL;
lines = NULL;
//fprintf(stderr, "mmu_cache_init: mallloc beg size %d,sets 0x%x\n", sizeof(cache_set_t) * set,sets);
//exit(-1);
sets = (cache_set_t *) malloc (sizeof (cache_set_t) * set);
if (sets == NULL) {
ERROR_LOG(ARM11, "set malloc size %d\n", sizeof (cache_set_t) * set);
goto sets_error;
}
//fprintf(stderr, "mmu_cache_init: mallloc end sets 0x%x\n", sets);
cache_t->sets = sets;
/*init cache set */
for (i = 0; i < set; i++) {
/*alloc cache line */
lines = (cache_line_t *) malloc (sizeof (cache_line_t) * way);
if (lines == NULL) {
ERROR_LOG(ARM11, "line malloc size %d\n",
sizeof (cache_line_t) * way);
goto lines_error;
}
/*init cache line */
for (j = 0; j < way; j++) {
lines[j].tag = 0; //invalid
lines[j].data = (ARMword *) malloc (width);
if (lines[j].data == NULL) {
ERROR_LOG(ARM11, "data alloc size %d\n", width);
goto data_error;
}
}
sets[i].lines = lines;
sets[i].cycle = 0;
}
cache_t->width = width;
cache_t->set = set;
cache_t->way = way;
cache_t->w_mode = w_mode;
return 0;
data_error:
/*free data */
while (j-- > 0)
free (lines[j].data);
/*free data error line */
free (lines);
lines_error:
/*free lines already alloced */
while (i-- > 0) {
for (j = 0; j < way; j++)
free (sets[i].lines[j].data);
free (sets[i].lines);
}
/*free sets */
free (sets);
sets_error:
return -1;
};
/* free a cache_t's inner data, the ptr self is not freed,
* when needed do like below:
* mmu_cache_exit(cache);
* free(cache_t);
*
* @cache_t : the cache_t to free
*/
void
mmu_cache_exit (cache_s * cache_t)
{
int i, j;
cache_set_t *sets, *set;
cache_line_t *lines, *line;
/*free all set */
sets = cache_t->sets;
for (set = sets, i = 0; i < cache_t->set; i++, set++) {
/*free all line */
lines = set->lines;
for (line = lines, j = 0; j < cache_t->way; j++, line++)
free (line->data);
free (lines);
}
free (sets);
}
/* mmu cache search
*
* @state :ARMul_State
* @cache_t :cache_t to search
* @va :virtual address
*
* $ NULL: no cache match
* cache :cache matched
*/
cache_line_t *
mmu_cache_search (ARMul_State * state, cache_s * cache_t, ARMword va)
{
int i;
int set = va_cache_set (va, cache_t);
ARMword tag = va_cache_align (va, cache_t);
cache_line_t *cache;
cache_set_t *cache_set = cache_t->sets + set;
for (i = 0, cache = cache_set->lines; i < cache_t->way; i++, cache++) {
if ((cache->tag & TAG_VALID_FLAG)
&& (tag == va_cache_align (cache->tag, cache_t)))
return cache;
}
return NULL;
}
/* mmu cache search by set/index
*
* @state :ARMul_State
* @cache_t :cache_t to search
* @index :set/index value.
*
* $ NULL: no cache match
* cache :cache matched
*/
cache_line_t *
mmu_cache_search_by_index (ARMul_State * state, cache_s * cache_t,
ARMword index)
{
int way = cache_t->way;
int set_v = index_cache_set (index, cache_t);
int i = 0, index_v = 0;
cache_set_t *set;
while ((way >>= 1) >= 1)
i++;
index_v = index >> (32 - i);
set = cache_t->sets + set_v;
return set->lines + index_v;
}
/* mmu cache alloc
*
* @state :ARMul_State
* @cache_t :cache_t to alloc from
* @va :virtual address that require cache alloc, need not cache aligned
* @pa :physical address of va
*
* $ cache_alloced, always alloc OK
*/
cache_line_t *
mmu_cache_alloc (ARMul_State * state, cache_s * cache_t, ARMword va,
ARMword pa)
{
cache_line_t *cache;
cache_set_t *set;
int i;
va = va_cache_align (va, cache_t);
pa = va_cache_align (pa, cache_t);
set = &cache_t->sets[va_cache_set (va, cache_t)];
/*robin-round */
cache = &set->lines[set->cycle++];
if (set->cycle == cache_t->way)
set->cycle = 0;
if (cache_t->w_mode == CACHE_WRITE_BACK) {
ARMword t;
/*if cache valid, try to write back */
if (cache->tag & TAG_VALID_FLAG) {
mmu_cache_write_back (state, cache_t, cache);
}
/*read in cache_line */
t = pa;
for (i = 0; i < (cache_t->width >> WORD_SHT);
i++, t += WORD_SIZE) {
//cache->data[i] = mem_read_word (state, t);
bus_read(32, t, &cache->data[i]);
}
}
/*store tag and pa */
cache->tag = va | TAG_VALID_FLAG;
cache->pa = pa;
return cache;
};
/* mmu_cache_write_back write cache data to memory
* @state
* @cache_t :cache_t of the cache line
* @cache : cache line
*/
void
mmu_cache_write_back (ARMul_State * state, cache_s * cache_t,
cache_line_t * cache)
{
ARMword pa = cache->pa;
int nw = cache_t->width >> WORD_SHT;
ARMword *data = cache->data;
int i;
int t0, t1, t2;
if ((cache->tag & 1) == 0)
return;
switch (cache->
tag & ~1 & (TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY)) {
case 0:
return;
case TAG_FIRST_HALF_DIRTY:
nw /= 2;
break;
case TAG_LAST_HALF_DIRTY:
nw /= 2;
pa += nw << WORD_SHT;
data += nw;
break;
case TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY:
break;
}
for (i = 0; i < nw; i++, data++, pa += WORD_SIZE)
//mem_write_word (state, pa, *data);
bus_write(32, pa, *data);
cache->tag &= ~(TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY);
};
/* mmu_cache_clean: clean a cache of va in cache_t
*
* @state :ARMul_State
* @cache_t :cache_t to clean
* @va :virtaul address
*/
void
mmu_cache_clean (ARMul_State * state, cache_s * cache_t, ARMword va)
{
cache_line_t *cache;
cache = mmu_cache_search (state, cache_t, va);
if (cache)
mmu_cache_write_back (state, cache_t, cache);
}
/* mmu_cache_clean_by_index: clean a cache by set/index format value
*
* @state :ARMul_State
* @cache_t :cache_t to clean
* @va :set/index format value
*/
void
mmu_cache_clean_by_index (ARMul_State * state, cache_s * cache_t,
ARMword index)
{
cache_line_t *cache;
cache = mmu_cache_search_by_index (state, cache_t, index);
if (cache)
mmu_cache_write_back (state, cache_t, cache);
}
/* mmu_cache_invalidate : invalidate a cache of va
*
* @state :ARMul_State
* @cache_t :cache_t to invalid
* @va :virt_addr to invalid
*/
void
mmu_cache_invalidate (ARMul_State * state, cache_s * cache_t, ARMword va)
{
cache_line_t *cache;
cache = mmu_cache_search (state, cache_t, va);
if (cache) {
mmu_cache_write_back (state, cache_t, cache);
cache->tag = 0;
}
}
/* mmu_cache_invalidate_by_index : invalidate a cache by index format
*
* @state :ARMul_State
* @cache_t :cache_t to invalid
* @index :set/index data
*/
void
mmu_cache_invalidate_by_index (ARMul_State * state, cache_s * cache_t,
ARMword index)
{
cache_line_t *cache;
cache = mmu_cache_search_by_index (state, cache_t, index);
if (cache) {
mmu_cache_write_back (state, cache_t, cache);
cache->tag = 0;
}
}
/* mmu_cache_invalidate_all
*
* @state:
* @cache_t
* */
void
mmu_cache_invalidate_all (ARMul_State * state, cache_s * cache_t)
{
int i, j;
cache_set_t *set;
cache_line_t *cache;
set = cache_t->sets;
for (i = 0; i < cache_t->set; i++, set++) {
cache = set->lines;
for (j = 0; j < cache_t->way; j++, cache++) {
mmu_cache_write_back (state, cache_t, cache);
cache->tag = 0;
}
}
};
void
mmu_cache_soft_flush (ARMul_State * state, cache_s * cache_t, ARMword pa)
{
ARMword set, way;
cache_line_t *cache;
pa = (pa / cache_t->width);
way = pa & (cache_t->way - 1);
set = (pa / cache_t->way) & (cache_t->set - 1);
cache = &cache_t->sets[set].lines[way];
mmu_cache_write_back (state, cache_t, cache);
cache->tag = 0;
}
cache_line_t* mmu_cache_dirty_cache(ARMul_State *state,cache_s *cache){
int i;
int j;
cache_line_t *cache_line = NULL;
cache_set_t *cache_set = cache->sets;
int sets = cache->set;
for (i = 0; i < sets; i++){
for(j = 0,cache_line = &cache_set[i].lines[0]; j < cache->way; j++,cache_line++){
if((cache_line->tag & TAG_FIRST_HALF_DIRTY) || (cache_line->tag & TAG_LAST_HALF_DIRTY))
return cache_line;
}
}
return NULL;
}

View file

@ -1,168 +0,0 @@
#ifndef _MMU_CACHE_H_
#define _MMU_CACHE_H_
typedef struct cache_line_t
{
ARMword tag; /* cache line align address |
bit2: last half dirty
bit1: first half dirty
bit0: cache valid flag
*/
ARMword pa; /*physical address */
ARMword *data; /*array of cached data */
} cache_line_t;
#define TAG_VALID_FLAG 0x00000001
#define TAG_FIRST_HALF_DIRTY 0x00000002
#define TAG_LAST_HALF_DIRTY 0x00000004
/*cache set association*/
typedef struct cache_set_s
{
cache_line_t *lines;
int cycle;
} cache_set_t;
enum
{
CACHE_WRITE_BACK,
CACHE_WRITE_THROUGH,
};
typedef struct cache_s
{
int width; /*bytes in a line */
int way; /*way of set asscociate */
int set; /*num of set */
int w_mode; /*write back or write through */
//int a_mode; /*alloc mode: random or round-bin*/
cache_set_t *sets;
/**/} cache_s;
typedef struct cache_desc_s
{
int width;
int way;
int set;
int w_mode;
// int a_mode;
} cache_desc_t;
/*virtual address to cache set index*/
#define va_cache_set(va, cache_t) \
(((va) / (cache_t)->width) & ((cache_t)->set - 1))
/*virtual address to cahce line aligned*/
#define va_cache_align(va, cache_t) \
((va) & ~((cache_t)->width - 1))
/*virtaul address to cache line word index*/
#define va_cache_index(va, cache_t) \
(((va) & ((cache_t)->width - 1)) >> WORD_SHT)
/*see Page 558 in arm manual*/
/*set/index format value to cache set value*/
#define index_cache_set(index, cache_t) \
(((index) / (cache_t)->width) & ((cache_t)->set - 1))
/*************************cache********************/
/* mmu cache init
*
* @cache_t :cache_t to init
* @width :cache line width in byte
* @way :way of each cache set
* @set :cache set num
* @w_mode :cache w_mode
*
* $ -1: error
* 0: sucess
*/
int
mmu_cache_init (cache_s * cache_t, int width, int way, int set, int w_mode);
/* free a cache_t's inner data, the ptr self is not freed,
* when needed do like below:
* mmu_cache_exit(cache);
* free(cache_t);
*
* @cache_t : the cache_t to free
*/
void mmu_cache_exit (cache_s * cache_t);
/* mmu cache search
*
* @state :ARMul_State
* @cache_t :cache_t to search
* @va :virtual address
*
* $ NULL: no cache match
* cache :cache matched
* */
cache_line_t *mmu_cache_search (ARMul_State * state, cache_s * cache_t,
ARMword va);
/* mmu cache search by set/index
*
* @state :ARMul_State
* @cache_t :cache_t to search
* @index :set/index value.
*
* $ NULL: no cache match
* cache :cache matched
* */
cache_line_t *mmu_cache_search_by_index (ARMul_State * state,
cache_s * cache_t, ARMword index);
/* mmu cache alloc
*
* @state :ARMul_State
* @cache_t :cache_t to alloc from
* @va :virtual address that require cache alloc, need not cache aligned
* @pa :physical address of va
*
* $ cache_alloced, always alloc OK
*/
cache_line_t *mmu_cache_alloc (ARMul_State * state, cache_s * cache_t,
ARMword va, ARMword pa);
/* mmu_cache_write_back write cache data to memory
*
* @state:
* @cache_t :cache_t of the cache line
* @cache : cache line
*/
void
mmu_cache_write_back (ARMul_State * state, cache_s * cache_t,
cache_line_t * cache);
/* mmu_cache_clean: clean a cache of va in cache_t
*
* @state :ARMul_State
* @cache_t :cache_t to clean
* @va :virtaul address
*/
void mmu_cache_clean (ARMul_State * state, cache_s * cache_t, ARMword va);
void
mmu_cache_clean_by_index (ARMul_State * state, cache_s * cache_t,
ARMword index);
/* mmu_cache_invalidate : invalidate a cache of va
*
* @state :ARMul_State
* @cache_t :cache_t to invalid
* @va :virt_addr to invalid
*/
void
mmu_cache_invalidate (ARMul_State * state, cache_s * cache_t, ARMword va);
void
mmu_cache_invalidate_by_index (ARMul_State * state, cache_s * cache_t,
ARMword index);
void mmu_cache_invalidate_all (ARMul_State * state, cache_s * cache_t);
void
mmu_cache_soft_flush (ARMul_State * state, cache_s * cache_t, ARMword pa);
cache_line_t* mmu_cache_dirty_cache(ARMul_State * state, cache_s * cache_t);
#endif /*_MMU_CACHE_H_*/

File diff suppressed because it is too large Load diff

View file

@ -1,126 +0,0 @@
#include "core/arm/skyeye_common/armdefs.h"
/*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu*/
ARMword rb_masks[] = {
0x0, //RB_INVALID
4, //RB_1
16, //RB_4
32, //RB_8
};
/*mmu_rb_init
* @rb_t :rb_t to init
* @num :number of entry
* */
int
mmu_rb_init (rb_s * rb_t, int num)
{
int i;
rb_entry_t *entrys;
entrys = (rb_entry_t *) malloc (sizeof (*entrys) * num);
if (entrys == NULL) {
printf ("SKYEYE:mmu_rb_init malloc error\n");
return -1;
}
for (i = 0; i < num; i++) {
entrys[i].type = RB_INVALID;
entrys[i].fault = NO_FAULT;
}
rb_t->entrys = entrys;
rb_t->num = num;
return 0;
}
/*mmu_rb_exit*/
void
mmu_rb_exit (rb_s * rb_t)
{
free (rb_t->entrys);
};
/*mmu_rb_search
* @rb_t :rb_t to serach
* @va :va address to math
*
* $ NULL :not match
* NO-NULL:
* */
rb_entry_t *
mmu_rb_search (rb_s * rb_t, ARMword va)
{
int i;
rb_entry_t *rb = rb_t->entrys;
DEBUG_LOG(ARM11, "va = %x\n", va);
for (i = 0; i < rb_t->num; i++, rb++) {
//2004-06-06 lyh bug from wenye@cs.ucsb.edu
if (rb->type) {
if ((va >= rb->va)
&& (va < (rb->va + rb_masks[rb->type])))
return rb;
}
}
return NULL;
};
void
mmu_rb_invalidate_entry (rb_s * rb_t, int i)
{
rb_t->entrys[i].type = RB_INVALID;
}
void
mmu_rb_invalidate_all (rb_s * rb_t)
{
int i;
for (i = 0; i < rb_t->num; i++)
mmu_rb_invalidate_entry (rb_t, i);
};
void
mmu_rb_load (ARMul_State * state, rb_s * rb_t, int i_rb, int type, ARMword va)
{
rb_entry_t *rb;
int i;
ARMword max_start, min_end;
fault_t fault;
tlb_entry_t *tlb;
/*align va according to type */
va &= ~(rb_masks[type] - 1);
/*invalidate all RB match [va, va + rb_masks[type]] */
for (rb = rb_t->entrys, i = 0; i < rb_t->num; i++, rb++) {
if (rb->type) {
max_start = max (va, rb->va);
min_end =
min (va + rb_masks[type],
rb->va + rb_masks[rb->type]);
if (max_start < min_end)
rb->type = RB_INVALID;
}
}
/*load word */
rb = &rb_t->entrys[i_rb];
rb->type = type;
fault = translate (state, va, D_TLB (), &tlb);
if (fault) {
rb->fault = fault;
return;
}
fault = check_access (state, va, tlb, 1);
if (fault) {
rb->fault = fault;
return;
}
rb->fault = NO_FAULT;
va = tlb_va_to_pa (tlb, va);
//2004-06-06 lyh bug from wenye@cs.ucsb.edu
for (i = 0; i < (rb_masks[type] / 4); i++, va += WORD_SIZE) {
//rb->data[i] = mem_read_word (state, va);
bus_read(32, va, &rb->data[i]);
};
}

View file

@ -1,55 +0,0 @@
#ifndef _MMU_RB_H
#define _MMU_RB_H
enum rb_type_t
{
RB_INVALID = 0, //invalid
RB_1, //1 word
RB_4, //4 word
RB_8, //8 word
};
/*bytes of each rb_type*/
extern ARMword rb_masks[];
#define RB_WORD_NUM 8
typedef struct rb_entry_s
{
ARMword data[RB_WORD_NUM]; //array to store data
ARMword va; //first word va
int type; //rb type
fault_t fault; //fault set by rb alloc
} rb_entry_t;
typedef struct rb_s
{
int num;
rb_entry_t *entrys;
} rb_s;
/*mmu_rb_init
* @rb_t :rb_t to init
* @num :number of entry
* */
int mmu_rb_init (rb_s * rb_t, int num);
/*mmu_rb_exit*/
void mmu_rb_exit (rb_s * rb_t);
/*mmu_rb_search
* @rb_t :rb_t to serach
* @va :va address to math
*
* $ NULL :not match
* NO-NULL:
* */
rb_entry_t *mmu_rb_search (rb_s * rb_t, ARMword va);
void mmu_rb_invalidate_entry (rb_s * rb_t, int i);
void mmu_rb_invalidate_all (rb_s * rb_t);
void mmu_rb_load (ARMul_State * state, rb_s * rb_t, int i_rb,
int type, ARMword va);
#endif /*_MMU_RB_H_*/

View file

@ -1,864 +0,0 @@
/*
armmmu.c - Memory Management Unit emulation.
ARMulator extensions for the ARM7100 family.
Copyright (C) 1999 Ben Williamson
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
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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
*/
#include <assert.h>
#include <string.h>
#include "core/arm/skyeye_common/armdefs.h"
/**
* The interface of read data from bus
*/
int bus_read(short size, int addr, uint32_t * value) {
ERROR_LOG(ARM11, "unimplemented bus_read");
return 0;
}
/**
* The interface of write data from bus
*/
int bus_write(short size, int addr, uint32_t value) {
ERROR_LOG(ARM11, "unimplemented bus_write");
return 0;
}
typedef struct sa_mmu_desc_s
{
int i_tlb;
cache_desc_t i_cache;
int d_tlb;
cache_desc_t main_d_cache;
cache_desc_t mini_d_cache;
int rb;
wb_desc_t wb;
} sa_mmu_desc_t;
static sa_mmu_desc_t sa11xx_mmu_desc = {
32,
{32, 32, 16, CACHE_WRITE_BACK},
32,
{32, 32, 8, CACHE_WRITE_BACK},
{32, 2, 8, CACHE_WRITE_BACK},
4,
//{8, 4}, for word size
{8, 16}, //for byte size, chy 2003-07-11
};
static fault_t sa_mmu_write (ARMul_State * state, ARMword va, ARMword data,
ARMword datatype);
static fault_t sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data,
ARMword datatype);
static fault_t update_cache (ARMul_State * state, ARMword va, ARMword data,
ARMword datatype, cache_line_t * cache,
cache_s * cache_t, ARMword real_va);
void
mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa,
ARMbyte * data, int n);
int
sa_mmu_init (ARMul_State * state)
{
sa_mmu_desc_t *desc;
cache_desc_t *c_desc;
state->mmu.control = 0x70;
state->mmu.translation_table_base = 0xDEADC0DE;
state->mmu.domain_access_control = 0xDEADC0DE;
state->mmu.fault_status = 0;
state->mmu.fault_address = 0;
state->mmu.process_id = 0;
desc = &sa11xx_mmu_desc;
if (mmu_tlb_init (I_TLB (), desc->i_tlb)) {
ERROR_LOG(ARM11, "i_tlb init %d\n", -1);
goto i_tlb_init_error;
}
c_desc = &desc->i_cache;
if (mmu_cache_init (I_CACHE (), c_desc->width, c_desc->way,
c_desc->set, c_desc->w_mode)) {
ERROR_LOG(ARM11, "i_cache init %d\n", -1);
goto i_cache_init_error;
}
if (mmu_tlb_init (D_TLB (), desc->d_tlb)) {
ERROR_LOG(ARM11, "d_tlb init %d\n", -1);
goto d_tlb_init_error;
}
c_desc = &desc->main_d_cache;
if (mmu_cache_init (MAIN_D_CACHE (), c_desc->width, c_desc->way,
c_desc->set, c_desc->w_mode)) {
ERROR_LOG(ARM11, "main_d_cache init %d\n", -1);
goto main_d_cache_init_error;
}
c_desc = &desc->mini_d_cache;
if (mmu_cache_init (MINI_D_CACHE (), c_desc->width, c_desc->way,
c_desc->set, c_desc->w_mode)) {
ERROR_LOG(ARM11, "mini_d_cache init %d\n", -1);
goto mini_d_cache_init_error;
}
if (mmu_wb_init (WB (), desc->wb.num, desc->wb.nb)) {
ERROR_LOG(ARM11, "wb init %d\n", -1);
goto wb_init_error;
}
if (mmu_rb_init (RB (), desc->rb)) {
ERROR_LOG(ARM11, "rb init %d\n", -1);
goto rb_init_error;
}
return 0;
rb_init_error:
mmu_wb_exit (WB ());
wb_init_error:
mmu_cache_exit (MINI_D_CACHE ());
mini_d_cache_init_error:
mmu_cache_exit (MAIN_D_CACHE ());
main_d_cache_init_error:
mmu_tlb_exit (D_TLB ());
d_tlb_init_error:
mmu_cache_exit (I_CACHE ());
i_cache_init_error:
mmu_tlb_exit (I_TLB ());
i_tlb_init_error:
return -1;
}
void
sa_mmu_exit (ARMul_State * state)
{
mmu_rb_exit (RB ());
mmu_wb_exit (WB ());
mmu_cache_exit (MINI_D_CACHE ());
mmu_cache_exit (MAIN_D_CACHE ());
mmu_tlb_exit (D_TLB ());
mmu_cache_exit (I_CACHE ());
mmu_tlb_exit (I_TLB ());
};
static fault_t
sa_mmu_load_instr (ARMul_State * state, ARMword va, ARMword * instr)
{
fault_t fault;
tlb_entry_t *tlb;
cache_line_t *cache;
int c; //cache bit
ARMword pa; //physical addr
static int debug_count = 0; //used for debug
DEBUG_LOG(ARM11, "va = %x\n", va);
va = mmu_pid_va_map (va);
if (MMU_Enabled) {
/*align check */
if ((va & (WORD_SIZE - 1)) && MMU_Aligned) {
DEBUG_LOG(ARM11, "align\n");
return ALIGNMENT_FAULT;
}
else
va &= ~(WORD_SIZE - 1);
/*translate tlb */
fault = translate (state, va, I_TLB (), &tlb);
if (fault) {
DEBUG_LOG(ARM11, "translate\n");
return fault;
}
/*check access */
fault = check_access (state, va, tlb, 1);
if (fault) {
DEBUG_LOG(ARM11, "check_fault\n");
return fault;
}
}
/*search cache no matter MMU enabled/disabled */
cache = mmu_cache_search (state, I_CACHE (), va);
if (cache) {
*instr = cache->data[va_cache_index (va, I_CACHE ())];
return NO_FAULT;
}
/*if MMU disabled or C flag is set alloc cache */
if (MMU_Disabled) {
c = 1;
pa = va;
}
else {
c = tlb_c_flag (tlb);
pa = tlb_va_to_pa (tlb, va);
}
if (c) {
int index;
debug_count++;
cache = mmu_cache_alloc (state, I_CACHE (), va, pa);
index = va_cache_index (va, I_CACHE ());
*instr = cache->data[va_cache_index (va, I_CACHE ())];
}
else
//*instr = mem_read_word (state, pa);
bus_read(32, pa, instr);
return NO_FAULT;
};
static fault_t
sa_mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
//ARMword temp,offset;
fault_t fault;
fault = sa_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE);
return fault;
}
static fault_t
sa_mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
//ARMword temp,offset;
fault_t fault;
fault = sa_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE);
return fault;
}
static fault_t
sa_mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
return sa_mmu_read (state, virt_addr, data, ARM_WORD_TYPE);
}
static fault_t
sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data,
ARMword datatype)
{
fault_t fault;
rb_entry_t *rb;
tlb_entry_t *tlb;
cache_line_t *cache;
ARMword pa, real_va, temp, offset;
DEBUG_LOG(ARM11, "va = %x\n", va);
va = mmu_pid_va_map (va);
real_va = va;
/*if MMU disabled, memory_read */
if (MMU_Disabled) {
//*data = mem_read_word(state, va);
if (datatype == ARM_BYTE_TYPE)
//*data = mem_read_byte (state, va);
bus_read(8, va, data);
else if (datatype == ARM_HALFWORD_TYPE)
//*data = mem_read_halfword (state, va);
bus_read(16, va, data);
else if (datatype == ARM_WORD_TYPE)
//*data = mem_read_word (state, va);
bus_read(32, va, data);
else {
printf ("SKYEYE:1 sa_mmu_read error: unknown data type %d\n", datatype);
// skyeye_exit (-1);
}
return NO_FAULT;
}
/*align check */
if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
DEBUG_LOG(ARM11, "align\n");
return ALIGNMENT_FAULT;
} // else
va &= ~(WORD_SIZE - 1);
/*translate va to tlb */
fault = translate (state, va, D_TLB (), &tlb);
if (fault) {
DEBUG_LOG(ARM11, "translate\n");
return fault;
}
/*check access permission */
fault = check_access (state, va, tlb, 1);
if (fault)
return fault;
/*search in read buffer */
rb = mmu_rb_search (RB (), va);
if (rb) {
if (rb->fault)
return rb->fault;
*data = rb->data[(va & (rb_masks[rb->type] - 1)) >> WORD_SHT];
goto datatrans;
//return 0;
};
/*search main cache */
cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
if (cache) {
*data = cache->data[va_cache_index (va, MAIN_D_CACHE ())];
goto datatrans;
//return 0;
}
/*search mini cache */
cache = mmu_cache_search (state, MINI_D_CACHE (), va);
if (cache) {
*data = cache->data[va_cache_index (va, MINI_D_CACHE ())];
goto datatrans;
//return 0;
}
/*get phy_addr */
pa = tlb_va_to_pa (tlb, va);
if ((pa >= 0xe0000000) && (pa < 0xe8000000)) {
if (tlb_c_flag (tlb)) {
if (tlb_b_flag (tlb)) {
mmu_cache_soft_flush (state, MAIN_D_CACHE (),
pa);
}
else {
mmu_cache_soft_flush (state, MINI_D_CACHE (),
pa);
}
}
return NO_FAULT;
}
/*if Buffer, drain Write Buffer first */
if (tlb_b_flag (tlb))
mmu_wb_drain_all (state, WB ());
/*alloc cache or mem_read */
if (tlb_c_flag (tlb) && MMU_DCacheEnabled) {
cache_s *cache_t;
if (tlb_b_flag (tlb))
cache_t = MAIN_D_CACHE ();
else
cache_t = MINI_D_CACHE ();
cache = mmu_cache_alloc (state, cache_t, va, pa);
*data = cache->data[va_cache_index (va, cache_t)];
}
else {
//*data = mem_read_word(state, pa);
if (datatype == ARM_BYTE_TYPE)
//*data = mem_read_byte (state, pa | (real_va & 3));
bus_read(8, pa | (real_va & 3), data);
else if (datatype == ARM_HALFWORD_TYPE)
//*data = mem_read_halfword (state, pa | (real_va & 2));
bus_read(16, pa | (real_va & 2), data);
else if (datatype == ARM_WORD_TYPE)
//*data = mem_read_word (state, pa);
bus_read(32, pa, data);
else {
printf ("SKYEYE:2 sa_mmu_read error: unknown data type %d\n", datatype);
// skyeye_exit (-1);
}
return NO_FAULT;
}
datatrans:
if (datatype == ARM_HALFWORD_TYPE) {
temp = *data;
offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */
*data = (temp >> offset) & 0xffff;
}
else if (datatype == ARM_BYTE_TYPE) {
temp = *data;
offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */
*data = (temp >> offset & 0xffL);
}
end:
return NO_FAULT;
}
static fault_t
sa_mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data)
{
return sa_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE);
}
static fault_t
sa_mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data)
{
return sa_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE);
}
static fault_t
sa_mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data)
{
return sa_mmu_write (state, virt_addr, data, ARM_WORD_TYPE);
}
static fault_t
sa_mmu_write (ARMul_State * state, ARMword va, ARMword data, ARMword datatype)
{
tlb_entry_t *tlb;
cache_line_t *cache;
int b;
ARMword pa, real_va;
fault_t fault;
DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data);
va = mmu_pid_va_map (va);
real_va = va;
/*search instruction cache */
cache = mmu_cache_search (state, I_CACHE (), va);
if (cache) {
update_cache (state, va, data, datatype, cache, I_CACHE (),
real_va);
}
if (MMU_Disabled) {
//mem_write_word(state, va, data);
if (datatype == ARM_BYTE_TYPE)
//mem_write_byte (state, va, data);
bus_write(8, va, data);
else if (datatype == ARM_HALFWORD_TYPE)
//mem_write_halfword (state, va, data);
bus_write(16, va, data);
else if (datatype == ARM_WORD_TYPE)
//mem_write_word (state, va, data);
bus_write(32, va, data);
else {
printf ("SKYEYE:1 sa_mmu_write error: unknown data type %d\n", datatype);
// skyeye_exit (-1);
}
return NO_FAULT;
}
/*align check */
//if ((va & (WORD_SIZE - 1)) && MMU_Aligned){
if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
DEBUG_LOG(ARM11, "align\n");
return ALIGNMENT_FAULT;
} //else
va &= ~(WORD_SIZE - 1);
/*tlb translate */
fault = translate (state, va, D_TLB (), &tlb);
if (fault) {
DEBUG_LOG(ARM11, "translate\n");
return fault;
}
/*tlb check access */
fault = check_access (state, va, tlb, 0);
if (fault) {
DEBUG_LOG(ARM11, "check_access\n");
return fault;
}
/*search main cache */
cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
if (cache) {
update_cache (state, va, data, datatype, cache,
MAIN_D_CACHE (), real_va);
}
else {
/*search mini cache */
cache = mmu_cache_search (state, MINI_D_CACHE (), va);
if (cache) {
update_cache (state, va, data, datatype, cache,
MINI_D_CACHE (), real_va);
}
}
if (!cache) {
b = tlb_b_flag (tlb);
pa = tlb_va_to_pa (tlb, va);
if (b) {
if (MMU_WBEnabled) {
if (datatype == ARM_WORD_TYPE)
mmu_wb_write_bytes (state, WB (), pa,
(ARMbyte*)&data, 4);
else if (datatype == ARM_HALFWORD_TYPE)
mmu_wb_write_bytes (state, WB (),
(pa |
(real_va & 2)),
(ARMbyte*)&data, 2);
else if (datatype == ARM_BYTE_TYPE)
mmu_wb_write_bytes (state, WB (),
(pa |
(real_va & 3)),
(ARMbyte*)&data, 1);
}
else {
if (datatype == ARM_WORD_TYPE)
//mem_write_word (state, pa, data);
bus_write(32, pa, data);
else if (datatype == ARM_HALFWORD_TYPE)
/*
mem_write_halfword (state,
(pa |
(real_va & 2)),
data);
*/
bus_write(16, pa | (real_va & 2), data);
else if (datatype == ARM_BYTE_TYPE)
/*
mem_write_byte (state,
(pa | (real_va & 3)),
data);
*/
bus_write(8, pa | (real_va & 3), data);
}
}
else {
mmu_wb_drain_all (state, WB ());
if (datatype == ARM_WORD_TYPE)
//mem_write_word (state, pa, data);
bus_write(32, pa, data);
else if (datatype == ARM_HALFWORD_TYPE)
/*
mem_write_halfword (state,
(pa | (real_va & 2)),
data);
*/
bus_write(16, pa | (real_va & 2), data);
else if (datatype == ARM_BYTE_TYPE)
/*
mem_write_byte (state, (pa | (real_va & 3)),
data);
*/
bus_write(8, pa | (real_va & 3), data);
}
}
return NO_FAULT;
}
static fault_t
update_cache (ARMul_State * state, ARMword va, ARMword data, ARMword datatype,
cache_line_t * cache, cache_s * cache_t, ARMword real_va)
{
ARMword temp, offset;
ARMword index = va_cache_index (va, cache_t);
//cache->data[index] = data;
if (datatype == ARM_WORD_TYPE)
cache->data[index] = data;
else if (datatype == ARM_HALFWORD_TYPE) {
temp = cache->data[index];
offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */
cache->data[index] =
(temp & ~(0xffffL << offset)) | ((data & 0xffffL) <<
offset);
}
else if (datatype == ARM_BYTE_TYPE) {
temp = cache->data[index];
offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */
cache->data[index] =
(temp & ~(0xffL << offset)) | ((data & 0xffL) <<
offset);
}
if (index < (cache_t->width >> (WORD_SHT + 1)))
cache->tag |= TAG_FIRST_HALF_DIRTY;
else
cache->tag |= TAG_LAST_HALF_DIRTY;
return NO_FAULT;
}
ARMword
sa_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
{
mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15);
ARMword data;
switch (creg) {
case MMU_ID:
// printf("mmu_mrc read ID ");
data = 0x41007100; /* v3 */
data = state->cpu->cpu_val;
break;
case MMU_CONTROL:
// printf("mmu_mrc read CONTROL");
data = state->mmu.control;
break;
case MMU_TRANSLATION_TABLE_BASE:
// printf("mmu_mrc read TTB ");
data = state->mmu.translation_table_base;
break;
case MMU_DOMAIN_ACCESS_CONTROL:
// printf("mmu_mrc read DACR ");
data = state->mmu.domain_access_control;
break;
case MMU_FAULT_STATUS:
// printf("mmu_mrc read FSR ");
data = state->mmu.fault_status;
break;
case MMU_FAULT_ADDRESS:
// printf("mmu_mrc read FAR ");
data = state->mmu.fault_address;
break;
case MMU_PID:
data = state->mmu.process_id;
default:
printf ("mmu_mrc read UNKNOWN - reg %d\n", creg);
data = 0;
break;
}
// printf("\t\t\t\t\tpc = 0x%08x\n", state->Reg[15]);
*value = data;
return data;
}
void
sa_mmu_cache_ops (ARMul_State * state, ARMword instr, ARMword value)
{
int CRm, OPC_2;
CRm = BITS (0, 3);
OPC_2 = BITS (5, 7);
if (OPC_2 == 0 && CRm == 7) {
mmu_cache_invalidate_all (state, I_CACHE ());
mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
mmu_cache_invalidate_all (state, MINI_D_CACHE ());
return;
}
if (OPC_2 == 0 && CRm == 5) {
mmu_cache_invalidate_all (state, I_CACHE ());
return;
}
if (OPC_2 == 0 && CRm == 6) {
mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
mmu_cache_invalidate_all (state, MINI_D_CACHE ());
return;
}
if (OPC_2 == 1 && CRm == 6) {
mmu_cache_invalidate (state, MAIN_D_CACHE (), value);
mmu_cache_invalidate (state, MINI_D_CACHE (), value);
return;
}
if (OPC_2 == 1 && CRm == 0xa) {
mmu_cache_clean (state, MAIN_D_CACHE (), value);
mmu_cache_clean (state, MINI_D_CACHE (), value);
return;
}
if (OPC_2 == 4 && CRm == 0xa) {
mmu_wb_drain_all (state, WB ());
return;
}
ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
}
static void
sa_mmu_tlb_ops (ARMul_State * state, ARMword instr, ARMword value)
{
int CRm, OPC_2;
CRm = BITS (0, 3);
OPC_2 = BITS (5, 7);
if (OPC_2 == 0 && CRm == 0x7) {
mmu_tlb_invalidate_all (state, I_TLB ());
mmu_tlb_invalidate_all (state, D_TLB ());
return;
}
if (OPC_2 == 0 && CRm == 0x5) {
mmu_tlb_invalidate_all (state, I_TLB ());
return;
}
if (OPC_2 == 0 && CRm == 0x6) {
mmu_tlb_invalidate_all (state, D_TLB ());
return;
}
if (OPC_2 == 1 && CRm == 0x6) {
mmu_tlb_invalidate_entry (state, D_TLB (), value);
return;
}
ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
}
static void
sa_mmu_rb_ops (ARMul_State * state, ARMword instr, ARMword value)
{
int CRm, OPC_2;
CRm = BITS (0, 3);
OPC_2 = BITS (5, 7);
if (OPC_2 == 0x0 && CRm == 0x0) {
mmu_rb_invalidate_all (RB ());
return;
}
if (OPC_2 == 0x2) {
int idx = CRm & 0x3;
int type = ((CRm >> 2) & 0x3) + 1;
if ((idx < 4) && (type < 4))
mmu_rb_load (state, RB (), idx, type, value);
return;
}
if ((OPC_2 == 1) && (CRm < 4)) {
mmu_rb_invalidate_entry (RB (), CRm);
return;
}
ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
}
static ARMword
sa_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
{
mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15);
if (!strncmp (state->cpu->cpu_arch_name, "armv4", 5)) {
switch (creg) {
case MMU_CONTROL:
// printf("mmu_mcr wrote CONTROL ");
state->mmu.control = (value | 0x70) & 0xFFFD;
break;
case MMU_TRANSLATION_TABLE_BASE:
// printf("mmu_mcr wrote TTB ");
state->mmu.translation_table_base =
value & 0xFFFFC000;
break;
case MMU_DOMAIN_ACCESS_CONTROL:
// printf("mmu_mcr wrote DACR ");
state->mmu.domain_access_control = value;
break;
case MMU_FAULT_STATUS:
state->mmu.fault_status = value & 0xFF;
break;
case MMU_FAULT_ADDRESS:
state->mmu.fault_address = value;
break;
case MMU_CACHE_OPS:
sa_mmu_cache_ops (state, instr, value);
break;
case MMU_TLB_OPS:
sa_mmu_tlb_ops (state, instr, value);
break;
case MMU_SA_RB_OPS:
sa_mmu_rb_ops (state, instr, value);
break;
case MMU_SA_DEBUG:
break;
case MMU_SA_CP15_R15:
break;
case MMU_PID:
//2004-06-06 lyh, bug provided by wen ye wenye@cs.ucsb.edu
state->mmu.process_id = value & 0x7e000000;
break;
default:
printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
break;
}
}
return 0;
}
//teawater add for arm2x86 2005.06.24-------------------------------------------
static int
sa_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr)
{
fault_t fault;
tlb_entry_t *tlb;
virt_addr = mmu_pid_va_map (virt_addr);
if (MMU_Enabled) {
/*align check */
if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) {
DEBUG_LOG(ARM11, "align\n");
return ALIGNMENT_FAULT;
}
else
virt_addr &= ~(WORD_SIZE - 1);
/*translate tlb */
fault = translate (state, virt_addr, I_TLB (), &tlb);
if (fault) {
DEBUG_LOG(ARM11, "translate\n");
return fault;
}
/*check access */
fault = check_access (state, virt_addr, tlb, 1);
if (fault) {
DEBUG_LOG(ARM11, "check_fault\n");
return fault;
}
}
if (MMU_Disabled) {
*phys_addr = virt_addr;
}
else {
*phys_addr = tlb_va_to_pa (tlb, virt_addr);
}
return (0);
}
//AJ2D--------------------------------------------------------------------------
/*sa mmu_ops_t*/
mmu_ops_t sa_mmu_ops = {
sa_mmu_init,
sa_mmu_exit,
sa_mmu_read_byte,
sa_mmu_write_byte,
sa_mmu_read_halfword,
sa_mmu_write_halfword,
sa_mmu_read_word,
sa_mmu_write_word,
sa_mmu_load_instr,
sa_mmu_mcr,
sa_mmu_mrc,
//teawater add for arm2x86 2005.06.24-------------------------------------------
sa_mmu_v2p_dbct,
//AJ2D--------------------------------------------------------------------------
};

View file

@ -1,58 +0,0 @@
/*
sa_mmu.h - StrongARM Memory Management Unit emulation.
ARMulator extensions for SkyEye.
<lyhost@263.net>
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
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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
*/
#ifndef _SA_MMU_H_
#define _SA_MMU_H_
/**
* The interface of read data from bus
*/
int bus_read(short size, int addr, uint32_t * value);
/**
* The interface of write data from bus
*/
int bus_write(short size, int addr, uint32_t value);
typedef struct sa_mmu_s
{
tlb_s i_tlb;
cache_s i_cache;
tlb_s d_tlb;
cache_s main_d_cache;
cache_s mini_d_cache;
rb_s rb_t;
wb_s wb_t;
} sa_mmu_t;
#define I_TLB() (&state->mmu.u.sa_mmu.i_tlb)
#define I_CACHE() (&state->mmu.u.sa_mmu.i_cache)
#define D_TLB() (&state->mmu.u.sa_mmu.d_tlb)
#define MAIN_D_CACHE() (&state->mmu.u.sa_mmu.main_d_cache)
#define MINI_D_CACHE() (&state->mmu.u.sa_mmu.mini_d_cache)
#define WB() (&state->mmu.u.sa_mmu.wb_t)
#define RB() (&state->mmu.u.sa_mmu.rb_t)
extern mmu_ops_t sa_mmu_ops;
#endif /*_SA_MMU_H_*/

View file

@ -1,307 +0,0 @@
#include <assert.h>
#include "core/arm/skyeye_common/armdefs.h"
ARMword tlb_masks[] = {
0x00000000, /* TLB_INVALID */
0xFFFFF000, /* TLB_SMALLPAGE */
0xFFFF0000, /* TLB_LARGEPAGE */
0xFFF00000, /* TLB_SECTION */
0xFFFFF000, /*TLB_ESMALLPAGE, have TEX attirbute, only for XScale */
0xFFFFFC00 /* TLB_TINYPAGE */
};
/* This function encodes table 8-2 Interpreting AP bits,
returning non-zero if access is allowed. */
static int
check_perms (ARMul_State * state, int ap, int read)
{
int s, r, user;
s = state->mmu.control & CONTROL_SYSTEM;
r = state->mmu.control & CONTROL_ROM;
//chy 2006-02-15 , should consider system mode, don't conside 26bit mode
user = (state->Mode == USER32MODE) || (state->Mode == USER26MODE) || (state->Mode == SYSTEM32MODE);
switch (ap) {
case 0:
return read && ((s && !user) || r);
case 1:
return !user;
case 2:
return read || !user;
case 3:
return 1;
}
return 0;
}
fault_t
check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb,
int read)
{
int access;
state->mmu.last_domain = tlb->domain;
access = (state->mmu.domain_access_control >> (tlb->domain * 2)) & 3;
if ((access == 0) || (access == 2)) {
/* It's unclear from the documentation whether this
should always raise a section domain fault, or if
it should be a page domain fault in the case of an
L1 that describes a page table. In the ARM710T
datasheets, "Figure 8-9: Sequence for checking faults"
seems to indicate the former, while "Table 8-4: Priority
encoding of fault status" gives a value for FS[3210] in
the event of a domain fault for a page. Hmm. */
return SECTION_DOMAIN_FAULT;
}
if (access == 1) {
/* client access - check perms */
int subpage, ap;
switch (tlb->mapping) {
/*ks 2004-05-09
* only for XScale
* Extend Small Page(ESP) Format
* 31-12 bits the base addr of ESP
* 11-10 bits SBZ
* 9-6 bits TEX
* 5-4 bits AP
* 3 bit C
* 2 bit B
* 1-0 bits 11
* */
case TLB_ESMALLPAGE: //xj
subpage = 0;
//printf("TLB_ESMALLPAGE virt_addr=0x%x \n",virt_addr );
break;
case TLB_TINYPAGE:
subpage = 0;
//printf("TLB_TINYPAGE virt_addr=0x%x \n",virt_addr );
break;
case TLB_SMALLPAGE:
subpage = (virt_addr >> 10) & 3;
break;
case TLB_LARGEPAGE:
subpage = (virt_addr >> 14) & 3;
break;
case TLB_SECTION:
subpage = 3;
break;
default:
assert (0);
subpage = 0; /* cleans a warning */
}
ap = (tlb->perms >> (subpage * 2 + 4)) & 3;
if (!check_perms (state, ap, read)) {
if (tlb->mapping == TLB_SECTION) {
return SECTION_PERMISSION_FAULT;
}
else {
return SUBPAGE_PERMISSION_FAULT;
}
}
}
else { /* access == 3 */
/* manager access - don't check perms */
}
return NO_FAULT;
}
fault_t
translate (ARMul_State * state, ARMword virt_addr, tlb_s * tlb_t,
tlb_entry_t ** tlb)
{
*tlb = mmu_tlb_search (state, tlb_t, virt_addr);
if (!*tlb) {
/* walk the translation tables */
ARMword l1addr, l1desc;
tlb_entry_t entry;
l1addr = state->mmu.translation_table_base & 0xFFFFC000;
l1addr = (l1addr | (virt_addr >> 18)) & ~3;
//l1desc = mem_read_word (state, l1addr);
bus_read(32, l1addr, &l1desc);
switch (l1desc & 3) {
case 0:
/*
* according to Figure 3-9 Sequence for checking faults in arm manual,
* section translation fault should be returned here.
*/
{
return SECTION_TRANSLATION_FAULT;
}
case 3:
/* fine page table */
// dcl 2006-01-08
{
ARMword l2addr, l2desc;
l2addr = l1desc & 0xFFFFF000;
l2addr = (l2addr |
((virt_addr & 0x000FFC00) >> 8)) &
~3;
//l2desc = mem_read_word (state, l2addr);
bus_read(32, l2addr, &l2desc);
entry.virt_addr = virt_addr;
entry.phys_addr = l2desc;
entry.perms = l2desc & 0x00000FFC;
entry.domain = (l1desc >> 5) & 0x0000000F;
switch (l2desc & 3) {
case 0:
state->mmu.last_domain = entry.domain;
return PAGE_TRANSLATION_FAULT;
case 3:
entry.mapping = TLB_TINYPAGE;
break;
case 1:
// this is untested
entry.mapping = TLB_LARGEPAGE;
break;
case 2:
// this is untested
entry.mapping = TLB_SMALLPAGE;
break;
}
}
break;
case 1:
/* coarse page table */
{
ARMword l2addr, l2desc;
l2addr = l1desc & 0xFFFFFC00;
l2addr = (l2addr |
((virt_addr & 0x000FF000) >> 10)) &
~3;
//l2desc = mem_read_word (state, l2addr);
bus_read(32, l2addr, &l2desc);
entry.virt_addr = virt_addr;
entry.phys_addr = l2desc;
entry.perms = l2desc & 0x00000FFC;
entry.domain = (l1desc >> 5) & 0x0000000F;
//printf("SKYEYE:PAGE virt_addr = %x,l1desc=%x,phys_addr=%x\n",virt_addr,l1desc,entry.phys_addr);
//chy 2003-09-02 for xscale
switch (l2desc & 3) {
case 0:
state->mmu.last_domain = entry.domain;
return PAGE_TRANSLATION_FAULT;
case 3:
if (!state->is_XScale) {
state->mmu.last_domain =
entry.domain;
return PAGE_TRANSLATION_FAULT;
};
//ks 2004-05-09 xscale shold use Extend Small Page
//entry.mapping = TLB_SMALLPAGE;
entry.mapping = TLB_ESMALLPAGE; //xj
break;
case 1:
entry.mapping = TLB_LARGEPAGE;
break;
case 2:
entry.mapping = TLB_SMALLPAGE;
break;
}
}
break;
case 2:
/* section */
//printf("SKYEYE:WARNING: not implement section mapping incompletely\n");
//printf("SKYEYE:SECTION virt_addr = %x,l1desc=%x\n",virt_addr,l1desc);
//return SECTION_DOMAIN_FAULT;
//#if 0
entry.virt_addr = virt_addr;
entry.phys_addr = l1desc;
entry.perms = l1desc & 0x00000C0C;
entry.domain = (l1desc >> 5) & 0x0000000F;
entry.mapping = TLB_SECTION;
break;
//#endif
}
entry.virt_addr &= tlb_masks[entry.mapping];
entry.phys_addr &= tlb_masks[entry.mapping];
/* place entry in the tlb */
*tlb = &tlb_t->entrys[tlb_t->cycle];
tlb_t->cycle = (tlb_t->cycle + 1) % tlb_t->num;
**tlb = entry;
}
state->mmu.last_domain = (*tlb)->domain;
return NO_FAULT;
}
int
mmu_tlb_init (tlb_s * tlb_t, int num)
{
tlb_entry_t *e;
int i;
e = (tlb_entry_t *) malloc (sizeof (*e) * num);
if (e == NULL) {
ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*e) * num);
goto tlb_malloc_error;
}
tlb_t->entrys = e;
for (i = 0; i < num; i++, e++)
e->mapping = TLB_INVALID;
tlb_t->cycle = 0;
tlb_t->num = num;
return 0;
tlb_malloc_error:
return -1;
}
void
mmu_tlb_exit (tlb_s * tlb_t)
{
free (tlb_t->entrys);
};
void
mmu_tlb_invalidate_all (ARMul_State * state, tlb_s * tlb_t)
{
int entry;
for (entry = 0; entry < tlb_t->num; entry++) {
tlb_t->entrys[entry].mapping = TLB_INVALID;
}
tlb_t->cycle = 0;
}
void
mmu_tlb_invalidate_entry (ARMul_State * state, tlb_s * tlb_t, ARMword addr)
{
tlb_entry_t *tlb;
tlb = mmu_tlb_search (state, tlb_t, addr);
if (tlb) {
tlb->mapping = TLB_INVALID;
}
}
tlb_entry_t *
mmu_tlb_search (ARMul_State * state, tlb_s * tlb_t, ARMword virt_addr)
{
int entry;
for (entry = 0; entry < tlb_t->num; entry++) {
tlb_entry_t *tlb;
ARMword mask;
tlb = &(tlb_t->entrys[entry]);
if (tlb->mapping == TLB_INVALID) {
continue;
}
mask = tlb_masks[tlb->mapping];
if ((virt_addr & mask) == (tlb->virt_addr & mask)) {
return tlb;
}
}
return NULL;
}

View file

@ -1,87 +0,0 @@
#ifndef _MMU_TLB_H_
#define _MMU_TLB_H_
typedef enum tlb_mapping_t
{
TLB_INVALID = 0,
TLB_SMALLPAGE = 1,
TLB_LARGEPAGE = 2,
TLB_SECTION = 3,
TLB_ESMALLPAGE = 4,
TLB_TINYPAGE = 5
} tlb_mapping_t;
extern ARMword tlb_masks[];
/* Permissions bits in a TLB entry:
*
* 31 12 11 10 9 8 7 6 5 4 3 2 1 0
* +-------------+-----+-----+-----+-----+---+---+-------+
* Page:| | ap3 | ap2 | ap1 | ap0 | C | B | |
* +-------------+-----+-----+-----+-----+---+---+-------+
*
* 31 12 11 10 9 4 3 2 1 0
* +-------------+-----+-----------------+---+---+-------+
* Section: | | AP | | C | B | |
* +-------------+-----+-----------------+---+---+-------+
*/
/*
section:
section base address [31:20]
AP - table 8-2, page 8-8
domain
C,B
page:
page base address [31:16] or [31:12]
ap[3:0]
domain (from L1)
C,B
*/
typedef struct tlb_entry_t
{
ARMword virt_addr;
ARMword phys_addr;
ARMword perms;
ARMword domain;
tlb_mapping_t mapping;
} tlb_entry_t;
typedef struct tlb_s
{
int num; /*num of tlb entry */
int cycle; /*current tlb cycle */
tlb_entry_t *entrys;
} tlb_s;
#define tlb_c_flag(tlb) \
((tlb)->perms & 0x8)
#define tlb_b_flag(tlb) \
((tlb)->perms & 0x4)
#define tlb_va_to_pa(tlb, va) ((tlb->phys_addr & tlb_masks[tlb->mapping]) | (va & ~tlb_masks[tlb->mapping]))
fault_t
check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb,
int read);
fault_t
translate (ARMul_State * state, ARMword virt_addr, tlb_s * tlb_t,
tlb_entry_t ** tlb);
int mmu_tlb_init (tlb_s * tlb_t, int num);
void mmu_tlb_exit (tlb_s * tlb_t);
void mmu_tlb_invalidate_all (ARMul_State * state, tlb_s * tlb_t);
void
mmu_tlb_invalidate_entry (ARMul_State * state, tlb_s * tlb_t, ARMword addr);
tlb_entry_t *mmu_tlb_search (ARMul_State * state, tlb_s * tlb_t,
ARMword virt_addr);
#endif /*_MMU_TLB_H_*/

View file

@ -1,149 +0,0 @@
#include "core/arm/skyeye_common/armdefs.h"
/* wb_init
* @wb_t :wb_t to init
* @num :num of entrys
* @nb :num of byte of each entry
*
* $ -1:error
* 0:ok
* */
int
mmu_wb_init (wb_s * wb_t, int num, int nb)
{
int i;
wb_entry_t *entrys, *wb;
entrys = (wb_entry_t *) malloc (sizeof (*entrys) * num);
if (entrys == NULL) {
ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*entrys) * num);
goto entrys_malloc_error;
}
for (wb = entrys, i = 0; i < num; i++, wb++) {
/*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu */
//wb->data = (ARMword *)malloc(sizeof(ARMword) * nb);
wb->data = (ARMbyte *) malloc (nb);
if (wb->data == NULL) {
ERROR_LOG(ARM11, "malloc size of %d\n", nb);
goto data_malloc_error;
}
};
wb_t->first = wb_t->last = wb_t->used = 0;
wb_t->num = num;
wb_t->nb = nb;
wb_t->entrys = entrys;
return 0;
data_malloc_error:
while (--i >= 0)
free (entrys[i].data);
free (entrys);
entrys_malloc_error:
return -1;
};
/* wb_exit
* @wb_t :wb_t to exit
* */
void
mmu_wb_exit (wb_s * wb_t)
{
int i;
wb_entry_t *wb;
wb = wb_t->entrys;
for (i = 0; i < wb_t->num; i++, wb++) {
free (wb->data);
}
free (wb_t->entrys);
};
/* wb_write_words :put words in Write Buffer
* @state: ARMul_State
* @wb_t: write buffer
* @pa: physical address
* @data: data ptr
* @n number of word to write
*
* Note: write buffer merge is not implemented, can be done late
* */
void
mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa,
ARMbyte * data, int n)
{
int i;
wb_entry_t *wb;
while (n) {
if (wb_t->num == wb_t->used) {
/*clean the last wb entry */
ARMword t;
wb = &wb_t->entrys[wb_t->last];
t = wb->pa;
for (i = 0; i < wb->nb; i++) {
//mem_write_byte (state, t, wb->data[i]);
bus_write(8, t, wb->data[i]);
//t += WORD_SIZE;
t++;
}
wb_t->last++;
if (wb_t->last == wb_t->num)
wb_t->last = 0;
wb_t->used--;
}
wb = &wb_t->entrys[wb_t->first];
i = (n < wb_t->nb) ? n : wb_t->nb;
wb->pa = pa;
//pa += i << WORD_SHT;
pa += i;
wb->nb = i;
//memcpy(wb->data, data, i << WORD_SHT);
memcpy (wb->data, data, i);
data += i;
n -= i;
wb_t->first++;
if (wb_t->first == wb_t->num)
wb_t->first = 0;
wb_t->used++;
};
//teawater add for set_dirty fflash cache function 2005.07.18-------------------
#ifdef DBCT
if (!skyeye_config.no_dbct) {
tb_setdirty (state, pa, NULL);
}
#endif
//AJ2D--------------------------------------------------------------------------
}
/* wb_drain_all
* @wb_t wb_t to drain
* */
void
mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t)
{
ARMword pa;
wb_entry_t *wb;
int i;
while (wb_t->used) {
wb = &wb_t->entrys[wb_t->last];
pa = wb->pa;
for (i = 0; i < wb->nb; i++) {
//mem_write_byte (state, pa, wb->data[i]);
bus_write(8, pa, wb->data[i]);
//pa += WORD_SIZE;
pa++;
}
wb_t->last++;
if (wb_t->last == wb_t->num)
wb_t->last = 0;
wb_t->used--;
};
}

View file

@ -1,63 +0,0 @@
#ifndef _MMU_WB_H_
#define _MMU_WB_H_
typedef struct wb_entry_s
{
ARMword pa; //phy_addr
ARMbyte *data; //data
int nb; //number byte to write
} wb_entry_t;
typedef struct wb_s
{
int num; //number of wb_entry
int nb; //number of byte of each entry
int first; //
int last; //
int used; //
wb_entry_t *entrys;
} wb_s;
typedef struct wb_desc_s
{
int num;
int nb;
} wb_desc_t;
/* wb_init
* @wb_t :wb_t to init
* @num :num of entrys
* @nw :num of word of each entry
*
* $ -1:error
* 0:ok
* */
int mmu_wb_init (wb_s * wb_t, int num, int nb);
/* wb_exit
* @wb_t :wb_t to exit
* */
void mmu_wb_exit (wb_s * wb);
/* wb_write_bytes :put bytess in Write Buffer
* @state: ARMul_State
* @wb_t: write buffer
* @pa: physical address
* @data: data ptr
* @n number of byte to write
*
* Note: write buffer merge is not implemented, can be done late
* */
void
mmu_wb_write_bytess (ARMul_State * state, wb_s * wb_t, ARMword pa,
ARMbyte * data, int n);
/* wb_drain_all
* @wb_t wb_t to drain
* */
void mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t);
#endif /*_MMU_WB_H_*/

File diff suppressed because it is too large Load diff

View file

@ -367,7 +367,6 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
int verbose; /* non-zero means print various messages like the banner */
mmu_state_t mmu;
int mmu_inited;
//mem_state_t mem;
/*remove io_state to skyeye_mach_*.c files */

View file

@ -134,121 +134,4 @@ typedef enum fault_t
} fault_t;
typedef struct mmu_ops_s
{
/*initilization */
int (*init) (ARMul_State * state);
/*free on exit */
void (*exit) (ARMul_State * state);
/*read byte data */
fault_t (*read_byte) (ARMul_State * state, ARMword va,
ARMword * data);
/*write byte data */
fault_t (*write_byte) (ARMul_State * state, ARMword va,
ARMword data);
/*read halfword data */
fault_t (*read_halfword) (ARMul_State * state, ARMword va,
ARMword * data);
/*write halfword data */
fault_t (*write_halfword) (ARMul_State * state, ARMword va,
ARMword data);
/*read word data */
fault_t (*read_word) (ARMul_State * state, ARMword va,
ARMword * data);
/*write word data */
fault_t (*write_word) (ARMul_State * state, ARMword va,
ARMword data);
/*load instr */
fault_t (*load_instr) (ARMul_State * state, ARMword va,
ARMword * instr);
/*mcr */
ARMword (*mcr) (ARMul_State * state, ARMword instr, ARMword val);
/*mrc */
ARMword (*mrc) (ARMul_State * state, ARMword instr, ARMword * val);
/*ywc 2005-04-16 convert virtual address to physics address */
int (*v2p_dbct) (ARMul_State * state, ARMword virt_addr,
ARMword * phys_addr);
} mmu_ops_t;
#include "core/arm/interpreter/mmu/tlb.h"
#include "core/arm/interpreter/mmu/rb.h"
#include "core/arm/interpreter/mmu/wb.h"
#include "core/arm/interpreter/mmu/cache.h"
/*special process mmu.h*/
#include "core/arm/interpreter/mmu/sa_mmu.h"
//#include "core/arm/interpreter/mmu/arm7100_mmu.h"
//#include "core/arm/interpreter/mmu/arm920t_mmu.h"
//#include "core/arm/interpreter/mmu/arm926ejs_mmu.h"
#include "core/arm/interpreter/mmu/arm1176jzf_s_mmu.h"
//#include "core/arm/interpreter/mmu/cortex_a9_mmu.h"
typedef struct mmu_state_t
{
ARMword control;
ARMword translation_table_base;
/* dyf 201-08-11 for arm1176 */
ARMword auxiliary_control;
ARMword coprocessor_access_control;
ARMword translation_table_base0;
ARMword translation_table_base1;
ARMword translation_table_ctrl;
/* arm1176 end */
ARMword domain_access_control;
ARMword fault_status;
ARMword fault_statusi; /* prefetch fault status */
ARMword fault_address;
ARMword last_domain;
ARMword process_id;
ARMword context_id;
ARMword thread_uro_id;
ARMword cache_locked_down;
ARMword tlb_locked_down;
//chy 2003-08-24 for xscale
ARMword cache_type; // 0
ARMword aux_control; // 1
ARMword copro_access; // 15
mmu_ops_t ops;
union
{
sa_mmu_t sa_mmu;
//arm7100_mmu_t arm7100_mmu;
//arm920t_mmu_t arm920t_mmu;
//arm926ejs_mmu_t arm926ejs_mmu;
} u;
} mmu_state_t;
int mmu_init (ARMul_State * state);
int mmu_reset (ARMul_State * state);
void mmu_exit (ARMul_State * state);
fault_t mmu_read_word (ARMul_State * state, ARMword virt_addr,
ARMword * data);
fault_t mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data);
fault_t mmu_load_instr (ARMul_State * state, ARMword virt_addr,
ARMword * instr);
ARMword mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value);
void mmu_mcr (ARMul_State * state, ARMword instr, ARMword value);
/*ywc 20050416*/
int mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr,
ARMword * phys_addr);
fault_t
mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data);
fault_t
mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data);
fault_t
mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data);
fault_t
mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data);
fault_t
mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data);
fault_t
mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data);
#endif /* _ARMMMU_H_ */