📄 arm7100_mmu.c
字号:
}
return NO_FAULT;
}
// if ((virt_addr & 3) && (state->mmu.control & CONTROL_ALIGN_FAULT)) {
if ((virt_addr & 3) && (datatype == ARM_WORD_TYPE)
&& (state->mmu.control & CONTROL_ALIGN_FAULT) || \
(virt_addr & 1)
&& (datatype == ARM_HALFWORD_TYPE)
&& (state->mmu.control & CONTROL_ALIGN_FAULT))
{
fprintf (stderr, "SKYEYE, a71_mmu_write ALIGNMENT_FAULT\n");
return ALIGNMENT_FAULT;
}
if (state->mmu.control & CONTROL_CACHE)
{
cache_line_t * cache;
cache = mmu_cache_search (state, CACHE (), virt_addr);
if (cache)
{
if (datatype == ARM_WORD_TYPE)
cache->data[(virt_addr >> 2) & 3] = data;
else if (datatype == ARM_HALFWORD_TYPE)
{
temp = cache->data[(virt_addr >> 2) & 3];
offset = (((ARMword) state->bigendSig * 2) ^ (virt_addr & 2)) << 3; /* bit offset into the word */
cache->data[(virt_addr >> 2) & 3] = \
(temp & ~(0xffffL << offset)) | ((data & 0xffffL) << offset);
}
else if (datatype == ARM_BYTE_TYPE)
{
temp = cache->data[(virt_addr >> 2) & 3];
offset = (((ARMword) state->bigendSig * 3) ^ (virt_addr & 3)) << 3; /* bit offset into the word */
cache->data[(virt_addr >> 2) & 3] = \
(temp & ~(0xffL << offset)) | ((data & 0xffL) << offset);
}
}
}
fault = translate (state, virt_addr, TLB (), &tlb);
if (fault)
{
return fault;
}
fault = check_access (state, virt_addr, tlb, 0);
if (fault)
{
return fault;
}
phys_addr = (tlb->phys_addr & tlb_masks[tlb->mapping]) |
(virt_addr & ~tlb_masks[tlb->mapping]);
if (datatype == ARM_BYTE_TYPE)
mem_write_byte (state, phys_addr, data);
else if (datatype == ARM_HALFWORD_TYPE)
mem_write_halfword (state, phys_addr, data);
else if (datatype == ARM_WORD_TYPE)
mem_write_word (state, phys_addr, data);
else
{
printf ("SKYEYE:2 a71_mmu_write error: unknown data type %d \n",
datatype);
exit (-1);
}
return NO_FAULT;
}
static ARMword
a71_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
{
mmu_regnum_t creg = BITS (16, 19) & 15;
ARMword data;
switch (creg)
{
case MMU_ID:
// printf("mmu_mrc read ID ");
#if 0
#ifdef MMU_V4
data = 0x41018100; /* v4 */
#else /*
*/
data = 0x41007100; /* v3 */
#endif /*
*/
#endif /*
*/
//data = 0x41007100;
data = skyeye_config.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;
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;
}
static void
a71_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
{
mmu_regnum_t creg = BITS (16, 19) & 15;
if (!strncmp (skyeye_config.cpu->cpu_arch_name, "armv4", 5))
{
switch (creg)
{
case MMU_CONTROL:
// printf("mmu_mcr wrote CONTROL ");
state->mmu.control = (value | 0x70) & 0xFFFF;
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;
//#ifdef MMU_V4
case MMU_FAULT_STATUS:
state->mmu.fault_status = value & 0xFF;
break;
case MMU_FAULT_ADDRESS:
state->mmu.fault_address = value;
break;
case MMU_V4_CACHE_OPS: /* incomplete */
if ((BITS (5, 7) & 7) == 0)
{
mmu_cache_invalidate_all (state, CACHE ());
}
break;
case MMU_V4_TLB_OPS: /* incomplete */
switch (BITS (5, 7) & 7)
{
case 0:
mmu_tlb_invalidate_all (state, TLB ());
break;
case 1:
mmu_tlb_invalidate_entry (state, TLB (), value);
break;
}
break;
default:
printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
break;
}
//#else
}
else
{
switch (creg)
{
case MMU_CONTROL:
state->mmu.control = (value | 0x70) & 0xFFFF;
break;
case MMU_TRANSLATION_TABLE_BASE:
state->mmu.translation_table_base = value & 0xFFFFC000;
break;
case MMU_DOMAIN_ACCESS_CONTROL:
state->mmu.domain_access_control = value;
break;
case MMU_V3_FLUSH_TLB:
// printf("mmu_mcr wrote FLUSH_TLB ");
mmu_tlb_invalidate_all (state, TLB ());
break;
case MMU_V3_FLUSH_TLB_ENTRY:
// printf("mmu_mcr wrote FLUSH_TLB_ENTRY");
mmu_tlb_invalidate_entry (state, TLB (), value);
break;
case MMU_V3_FLUSH_CACHE:
// printf("mmu_mcr wrote FLUSH_CACHE ");
mmu_cache_invalidate_all (state, CACHE ());
break;
default:
printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
break;
//#endif
}
}
// printf("\t\t\t\tpc = 0x%08x\n", state->Reg[15]);
}
static int
a71_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr,
ARMword * phys_addr)
{
tlb_entry_t * tlb;
ARMword temp, offset;
fault_t fault;
ARMword datatype = ARM_WORD_TYPE;
int ret = -1;
if ((virt_addr & 3) && (datatype == ARM_WORD_TYPE)
&& (state->mmu.control & CONTROL_ALIGN_FAULT) || \
(virt_addr & 1)
&& (datatype == ARM_HALFWORD_TYPE)
&& (state->mmu.control & CONTROL_ALIGN_FAULT))
{
fprintf (stderr, "SKYEYE, a71_mmu_read ALIGNMENT_FAULT\n");
goto out;
}
if (!(state->mmu.control & CONTROL_MMU))
{
*phys_addr = virt_addr;
}
else
{
fault = translate (state, virt_addr, TLB (), &tlb);
if (fault)
{
goto out;
}
fault = check_access (state, virt_addr, tlb, 1);
if (fault)
{
goto out;
}
*phys_addr = (tlb->phys_addr & tlb_masks[tlb->mapping]) |
(virt_addr & ~tlb_masks[tlb->mapping]);
}
ret = 0;
out:
return (ret);
}
#undef CACHE
#undef TLB
mmu_ops_t arm7100_mmu_ops =
{
a71_mmu_init,
a71_mmu_exit,
a71_mmu_read_byte,
a71_mmu_write_byte,
a71_mmu_read_halfword,
a71_mmu_write_halfword,
a71_mmu_read_word,
a71_mmu_write_word,
a71_mmu_read_word, // load instr
a71_mmu_mcr,
a71_mmu_mrc,
a71_mmu_v2p_dbct // ywc 2005-04-16 test
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -