📄 mapfile.c
字号:
return top->mem.page[0];
}
/*
* We fill the new page with data that, if the ARM tried to execute
* it, it will cause an undefined instruction trap (whether ARM or
* Thumb)
*/
for (i=0;i<ARMMAP_PAGESIZE/4;) {
page->memory[i++]=0xe7ff0010; /* an ARM undefined instruction */
/* The ARM undefined insruction has been chosen such that the
* first halfword is an innocuous Thumb instruction (B 0x2)
*/
page->memory[i++]=0xe800e800; /* a Thumb undefined instruction */
}
return page;
}
#endif
/*
* Generic memory interface. Just alter this for a memtype memory system
*/
/* Returns a PERIP_ value from minperip.h */
static INLINE int FindMemoryRegion(
MapfileState *top, ARMword address, ARMword *data, ARMul_acc acc,
Bus *bus)
{
/* first cycle of the access */
MemDescr *desc;
unsigned long prop = top->prop;
(void)data;
for (desc = &top->desc; desc; desc = desc->next) {
if (address >= desc->desc.start &&
address <= desc->desc.limit) {
desc->access_counts[acc & (WIDTH_MASK | acc_seq | acc_Nrw)]++;
desc->stats_are_valid = FALSE;
/* If we're looking for I-S cycles, then use the N cycle
* counter if we're on an I-S boundary
*/
if ((prop & MAP_SPOTISCYCLES) &&
acc_SEQ(acc) &&
acc_nMREQ(bus->last_acc)) {
/* Use the 'this width, idle, read/write' counter */
bus->cnt = desc->counter[(acc & (WIDTH_MASK | acc_Nrw)) | acc_Nmreq];
if (prop & MAP_AMBABUSCOUNTS) {
/* This count includes an extra cycle for AMBA decode. We
* don't need this for I-S cycles, so we need to remove it.
*/
if (bus->cnt > 0) bus->cnt--;
}
top->IS_cycles++;
} else
bus->cnt = desc->counter[acc & (WIDTH_MASK | acc_seq | acc_Nrw)];
if (bus->cnt) {
if (bus->cnt < 0) {
if (bus->cnt == -1) {/* abort */
bus->cnt = 0;
bus->last_acc = acc;
#ifdef VERBOSE_DABORT
printf("Mapfile DABORT addr:%08lx\n", (unsigned long)address);
#endif
return PERIP_DABORT /*-1*/;
}
/*
* otherwise, this is a 16-bit SEQ read
* - takes 1 cycle if top half of word,
* - takes -cnt-2 cycles otherwise.
*/
if ((address & 2) == 0) bus->cnt = -bus->cnt-2;
else break; /* i.e. fall through - 1 cycle */
}
bus->wait_states++;
bus->last_acc = acc;
return PERIP_BUSY /*0*/;
}
break; /* fall through */
} /* endif in-region */
} /* endfor */
if ((prop & MAP_AMBABUSCOUNTS) &&
acc_MREQ(acc) && acc_nSEQ(acc)) {
/* needs an address decode cycle */
bus->cnt = 1;
bus->wait_states++;
bus->last_acc = acc;
return PERIP_BUSY /*0*/;
}
return PERIP_OK /*1*/;
}
#if USE_BASE_MEMORY
#else
static int MemLookup(MapfileState *top, ARMword address, ARMword *data,
ARMul_acc acc)
{
unsigned int pageno;
mempage *page;
ARMword *ptr;
ARMword offset;
pageno = address >> PAGEBITS;
page=top->mem.page[pageno];
if (page == NULL) {
top->mem.page[pageno] = page = NewPage(top);
}
offset = address & OFFSETBITS_WORD;
ptr=(ARMword *)((char *)(page->memory)+offset);
#ifdef VERBOSE_MEMLOOKUP
printf("mapfile:MemLookup(A:%08lx T:%08lx)\n",
(unsigned long)address,(unsigned long)acc);
#endif
switch (acc & (ACCESS_SIZE_MASK | ACCESS_IDLE | ACCESS_WRITE) )
{
case BITS_8: /* read byte */
*data = ((unsigned8 *)ptr)[(address ^ top->byteAddrXor) & 3];
break;
case BITS_16: /* read half-word */
*data = *((unsigned16 *)(((char *)ptr)+
((address ^ top->hwordAddrXor) & 2)));
return 1;
case BITS_32: /* read word */
*data=*ptr;
return 1;
case BITS_64: /* read dword */
*data=*ptr;
if ((offset+4) & OFFSETBITS_WORD)
{
data[1]=ptr[1];
return 2;
}
break;
case BITS_8 | ACCESS_WRITE: /* write_byte */
if (HostEndian!=top->write_bigend) address^=3;
((unsigned8 *)ptr)[address & 3]=(unsigned8)(*data);
break;
case BITS_16 | ACCESS_WRITE: /* write half-word */
if (HostEndian!=top->write_bigend) address^=2;
*((unsigned16 *)(((char *)ptr)+(address & 2))) = (unsigned16)(*data);
break;
case BITS_32 | ACCESS_WRITE: /* write word */
*ptr=*data;
return 1;
case BITS_64 | ACCESS_WRITE:
*ptr=*data;
if ((offset+4) & OFFSETBITS_WORD)
{
ptr[1]=data[1];
return 2;
}
break;
case ACCESS_IDLE:
return 1;
default:
#ifdef VERBOSE_DABORT
printf("mapfile:MemLookup -> abort\n");
#endif
return PERIP_DABORT;
}
return PERIP_OK;
}
#endif
static int Mapfile_MemAccess(void *handle, ARMWord address, ARMWord *data,
unsigned acc)
{
MapfileState *top=(MapfileState *)handle;
#ifdef VERBOSE_ACCESS
/* if (ACCESS_IS_IDLE(acc)) */
{
printf("Mapfile_Access AD:%08lx AC:%04lx\n",
(unsigned long)address, (unsigned long)acc);
}
#endif
if (ACCESS_IS_REAL(acc))
{
++top->cycles.Total;
#ifdef VERBOSE_ACCOUNTED_ACCESS
printf("Mapfile_Access! AD:%08lx AC:%04lx\n",
(unsigned long)address, (unsigned long)acc);
#endif
if (acc_MREQ(acc)) {
if (top->d.cnt == 0 || acc != top->d.last_acc) {
int rv = FindMemoryRegion(top, address, data, acc, &top->d);
if (rv != PERIP_OK) {
ADVANCE_BUS_TIME;
return rv;
}
/* else fall through */
} else {
/* not the first cycle */
if (--top->d.cnt) {
top->d.wait_states++;
top->d.last_acc = acc;
ADVANCE_BUS_TIME;
return PERIP_BUSY;
}
/* else fall through */
}
} else {
if (acc_SEQ(acc)) {
top->cycles.NumCcycles++;
} else {
top->cycles.NumIcycles++;
}
}
top->d.cnt = 0;
top->d.last_acc = acc;
} /* endif ACCESS_IS_REAL */
#if USE_BASE_MEMORY /* T */
return top->child.x.basic.access(top->child.handle, address, data, acc);
#else
return MemLookup(top, address, data, acc);
#endif
}
static int Mapfile_MemAccessSA(void *handle,ARMWord address, ARMWord *data,
unsigned acc)
{
MapfileState *top=(MapfileState *)handle;
if (ACCESS_IS_REAL(acc)) {
Bus *bus;
if (acc_OPC(acc)) {
++top->cycles.Total;
bus = &top->i;
} else {
bus = &top->d;
}
if (acc_MREQ(acc)) {
if (bus->cnt == 0 || acc != bus->last_acc) {
int rv = FindMemoryRegion(top, address, data, acc, bus);
if (rv != PERIP_OK) {
ADVANCE_BUS_TIME;
return rv;
}
/* else fall through */
} else {
/* not the first cycle */
if (--bus->cnt) {
bus->wait_states++;
bus->last_acc = acc;
ADVANCE_BUS_TIME;
return PERIP_BUSY /*0*/;
}
/* else fall through */
}
/*
* On Harvard architectures there are four types of cycle -
* we'll reuse the four cycle counters for these:
*
* Instruction fetched, No data fetched N
* Instruction fetched, data fetched S
* No instruction fetched, No data fetched I
* No instruction fetched, data fetched C
*/
if (acc_OPC(acc)) {
/* End of cycle - account for access */
/* This access is either acc_LoadInstrN or acc_NoFetch */
if (top->harvard_data_flag) {
/* data fetched */
top->harvard_data_flag = FALSE;
top->cycles.NumScycles++; /* instr/data */
} else {
/* no data fetched */
top->cycles.NumNcycles++;/* instr/no data */
}
} else {
/* don't count on data accesses */
/* data fetched */
top->harvard_data_flag = TRUE;
}
} else {
if (acc_OPC(acc)) {
/* End of cycle - account for access */
/* This access is either acc_LoadInstrN or acc_NoFetch */
if (top->harvard_data_flag) {
/* data fetched */
top->harvard_data_flag = FALSE;
top->cycles.NumCcycles++; /* no instr/data */
} else {
/* no data fetched */
top->cycles.NumIcycles++;/* no instr/no data */
}
}
}
bus->cnt = 0;
bus->last_acc = acc;
}
#if USE_BASE_MEMORY
return top->child.x.basic.access(top->child.handle, address, data, acc);
#else
return MemLookup(top, address, data, acc);
#endif
}
static const ARMul_Cycles *Mapfile_ReadCycles(void *handle)
{
static ARMul_Cycles cycles;
MapfileState *top=(MapfileState *)handle;
if (!(top->prop & MAP_HARVARD)) {
ARMword n = 0, s = 0;
MemDescr *d;
for (d = &top->desc; d != NULL; d = d->next) {
ARMul_acc acc;
for (acc = 0; acc < 0x60; acc++) {
if (acc_MREQ(acc)) {
if (acc_SEQ(acc)) {
s += d->access_counts[acc];
} else {
n += d->access_counts[acc];
}
}
}
}
top->cycles.NumNcycles = n;
top->cycles.NumScycles = s;
}
/* if (top->prop & (MAP_COUNTWAIT | MAP_AMBABUSCOUNTS)) */
{
cycles.NumNcycles = top->cycles.NumNcycles;
cycles.NumScycles = top->cycles.NumScycles;
cycles.NumIcycles = top->cycles.NumIcycles + top->cycles.NumCcycles;
cycles.NumCcycles = top->d.wait_states + top->i.wait_states;
}
/* else {
* cycles = top->cycles;
* }
*/
cycles.Total = top->cycles.Total;
return &cycles;
}
static void Mapfile_MemAccessHarvard(void *handle,
ARMword daddr,ARMword *ddata, ARMul_acc dacc, int *drv,
ARMword iaddr,ARMword *idata, ARMul_acc iacc, int *irv)
{
#ifdef VERBOSE_Mapfile_MemAccessHarvard
printf("Mapfile_MemAccessHarvard BEGIN DA:%08lx DT:%04lx "
" IA:%08lx IT:%04lx DS:%i IS:%i\n",
(unsigned long)daddr,(unsigned long)dacc,
(unsigned long)iaddr,(unsigned long)iacc, *drv, *irv);
#endif
/* We do D then I because MemAccessSA expects that. */
if (!*drv)
*drv = Mapfile_MemAccessSA(handle,daddr,ddata,dacc);
else
Mapfile_MemAccessSA(handle,daddr,ddata,ACCESS_IDLE|ACCESS_DATA);
if (!*irv)
*irv = Mapfile_MemAccessSA(handle,iaddr,idata,iacc);
else
Mapfile_MemAccessSA(handle,iaddr,idata,ACCESS_IDLE|ACCESS_INSTR);
#ifdef VERBOSE_Mapfile_MemAccessHarvard
printf("Mapfile_MemAccessHarvard END -> DS:%i IS:%i\n",
*drv, *irv);
#endif
}
BEGIN_EXIT(Mapfile)
{
ARMword page;
MapfileState *top=state; /* (MapfileState *)handle */
memory *mem=&top->mem;
MemDescr *desc,*next;
/* free all truly allocated pages */
for (page=0; page<NUMPAGES; page++) {
mempage *pageptr= mem->page[page];
if (pagept
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -