📄 arm926ejs_mmu.c
字号:
/*tlb check access */ fault = check_access (state, va, tlb, 0); if (fault) { d_msg ("check_access\n"); return fault; } /*search main cache */ cache = mmu_cache_search (state, ARM926EJS_D_CACHE (), va); if (cache) { update_cache (state, va, data, datatype, cache, ARM926EJS_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, ARM926EJS_WB (), pa, &data, 4); else if (datatype == ARM_HALFWORD_TYPE) mmu_wb_write_bytes (state, ARM926EJS_WB (), (pa | (real_va & 2)), &data, 2); else if (datatype == ARM_BYTE_TYPE) mmu_wb_write_bytes (state, ARM926EJS_WB (), (pa | (real_va & 3)), &data, 1); } else { if (datatype == ARM_WORD_TYPE) mem_write_word (state, pa, data); else if (datatype == ARM_HALFWORD_TYPE) mem_write_halfword (state, (pa | (real_va & 2)), data); else if (datatype == ARM_BYTE_TYPE) mem_write_byte (state, (pa | (real_va & 3)), data); } } else { mmu_wb_drain_all (state, ARM926EJS_WB ()); if (datatype == ARM_WORD_TYPE) mem_write_word (state, pa, data); else if (datatype == ARM_HALFWORD_TYPE) mem_write_halfword (state, (pa | (real_va & 2)), data); else if (datatype == ARM_BYTE_TYPE) mem_write_byte (state, (pa | (real_va & 3)), data); } } return 0;}static fault_tupdate_cache (ARMul_State * state, ARMword va, ARMword data, ARMword datatype, cache_line_t * cache, cache_t * 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 0;}ARMwordarm926ejs_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value){ mmu_regnum_t creg = BITS (16, 19) & 0xf; int OPC_2 = BITS (5, 7) & 0x7; ARMword data; //printf("mmu_mrc read - reg %d\n", creg); switch (creg) { case MMU_ID: if (OPC_2 == 0) { data = state->cpu->cpu_val; } else if (OPC_2 == 1) /* ARM926EJS Cache type: * Ctype S Dsize Isize * Size assoc M Len Size assoc M Len *NS9750: 000 1110 1 00 0011 010 0 10 00 0100 010 0 10 *see ARM926ejs TRM P2-8 * */ data = 0x1D0D2112; else if (OPC_2 == 2) { /* TCM status */ data = 0x0; } break; case MMU_CONTROL: /* * 6:3 should be 1. * 11:10 should be 0 * 18,16 should be 1 * 17 should be 0 * 31:19 should be 0 * */ data = (state->mmu.control | 0x50078) & 0x0005F3FF;; break; case MMU_TRANSLATION_TABLE_BASE: data = state->mmu.translation_table_base & 0xFFFFC000; break; case MMU_DOMAIN_ACCESS_CONTROL: data = state->mmu.domain_access_control; break; case MMU_FAULT_STATUS: /* OPC_2 = 0: data FSR value * */ if (OPC_2 == 0) data = state->mmu.fault_status & 0x0FF; break; case MMU_FAULT_ADDRESS: data = state->mmu.fault_address; break; case MMU_CACHE_OPS: /* TODO */ //arm926ejs_mmu_cache_ops(state, instr, value); break; case MMU_TLB_LOCKDOWN: /* FIXME:tlb lock down */ data = state->mmu.tlb_locked_down; 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;}/* ARM926EJS Cache Operation, P44 * */voidarm926ejs_mmu_cache_ops (ARMul_State * state, ARMword instr, ARMword value){ int CRm, OPC_2; CRm = BITS (0, 3); OPC_2 = BITS (5, 7); //printf("%s - CRm: %d, OPC_2: %d\n", __FUNCTION__, CRm, OPC_2); if (OPC_2 == 0 && CRm == 7) { mmu_cache_invalidate_all (state, ARM926EJS_I_CACHE ()); mmu_cache_invalidate_all (state, ARM926EJS_D_CACHE ()); return; } if (OPC_2 == 0 && CRm == 5) { mmu_cache_invalidate_all (state, ARM926EJS_I_CACHE ()); return; } /*Invalidate ICache single entry **/ if (OPC_2 == 1 && CRm == 5) { mmu_cache_invalidate (state, ARM926EJS_I_CACHE (), value); return; } /* Invalidate ICache single entry Set/way */ if (OPC_2 == 2 && CRm == 5) { mmu_cache_invalidate_by_index (state, ARM926EJS_I_CACHE (), value); return; } /* TODO: * Prefetch ICache line (using MVA) * */ if (OPC_2 == 1 && CRm == 13) { //mmu_cache_invalidate(state, ARM926EJS_I_CACHE(), value); return; } if (OPC_2 == 0 && CRm == 6) { mmu_cache_invalidate_all (state, ARM926EJS_D_CACHE ()); return; } /* Invalidate DCache single entry (using MVA) * */ if (OPC_2 == 1 && CRm == 6) { mmu_cache_invalidate (state, ARM926EJS_D_CACHE (), value); return; } /* Invalidate DCache single entry Set/way */ if (OPC_2 == 2 && CRm == 6) { mmu_cache_invalidate_by_index (state, ARM926EJS_D_CACHE (), value); return; } /* Clean DCache single entry (using MVA) * */ if (OPC_2 == 1 && CRm == 0xa) { mmu_cache_clean (state, ARM926EJS_D_CACHE (), value); return; } /* Clean and Invalidate DCache entry (using MVA) * */ if (OPC_2 == 1 && CRm == 14) { mmu_cache_clean (state, ARM926EJS_D_CACHE (), value); mmu_cache_invalidate (state, ARM926EJS_D_CACHE (), value); return; } /* Clean DCache single entry (Set Way) * */ if (OPC_2 == 2 && CRm == 0xa) { mmu_cache_clean_by_index (state, ARM926EJS_D_CACHE (), value); return; } /* Clean and Invalidate DCache entry (Set/Way) * */ if (OPC_2 == 2 && CRm == 14) { mmu_cache_clean_by_index (state, ARM926EJS_D_CACHE (), value); mmu_cache_invalidate_by_index (state, ARM926EJS_D_CACHE (), value); return; } /* Drain write buffer * */ if (OPC_2 == 4 && CRm == 0xa) { mmu_wb_drain_all (state, ARM926EJS_WB ()); return; } /* FIXME: how to do a waiting operation? * Wait for a interrupt * */ if (OPC_2 == 4 && CRm == 0) { return; } err_msg ("Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);}static voidarm926ejs_mmu_tlb_ops (ARMul_State * state, ARMword instr, ARMword value){ int CRm, OPC_2; CRm = BITS (0, 3); OPC_2 = BITS (5, 7); //printf("%s - CRm: %d, OPC_2: %d\n", __FUNCTION__, CRm, OPC_2); if (OPC_2 == 0 && (CRm == 0x7) || (CRm == 0x6) || (CRm == 0x5)) { mmu_tlb_invalidate_all (state, ARM926EJS_MAIN_TLB ()); //mmu_tlb_invalidate_all(state, ARM926EJS_LOCKDOWN_TLB()); return; } if (OPC_2 == 1 && (CRm == 0x5 || (CRm == 0x7) || (CRm == 0x6))) { mmu_tlb_invalidate_entry (state, ARM926EJS_MAIN_TLB (), value); return; } err_msg ("Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);}static voidarm926ejs_mmu_cache_lockdown (ARMul_State * state, ARMword instr, ARMword value){ int OPC_2 = BITS (5, 7) & 0x7;}static voidarm926ejs_mmu_tlb_lockdown (ARMul_State * state, ARMword instr, ARMword value){}static ARMwordarm926ejs_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value){ mmu_regnum_t creg = BITS (16, 19) & 15; int OPC_2 = BITS (5, 7) & 0x7; //printf("mmu_mcr - reg %d\n", creg); switch (creg) { case MMU_CONTROL:// printf("mmu_mcr wrote CONTROL "); state->mmu.control = (value | 0x50078) & 0x0005F3FF; 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: if (OPC_2 == 0) state->mmu.fault_status = value & 0xFF; break; case MMU_FAULT_ADDRESS: state->mmu.fault_address = value; break; case MMU_CACHE_OPS: arm926ejs_mmu_cache_ops (state, instr, value); break; case MMU_TLB_OPS: arm926ejs_mmu_tlb_ops (state, instr, value); break; case MMU_CACHE_LOCKDOWN: /* * FIXME: cache lock down*/ break; case MMU_TLB_LOCKDOWN: /* FIXME:tlb lock down */ state->mmu.tlb_locked_down = value; break; case MMU_PID: /*0:24 should be zero. */ state->mmu.process_id = value & 0xfe000000; break; default: printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); break; }}//teawater add for arm2x86 2005.06.19-------------------------------------------static intarm926ejs_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) { d_msg ("align\n"); return ALIGNMENT_FAULT; } else virt_addr &= ~(WORD_SIZE - 1); /*translate tlb */ fault = translate (state, virt_addr, ARM926EJS_MAIN_TLB (), &tlb); if (fault) { d_msg ("translate\n"); return fault; } /*check access */ fault = check_access (state, virt_addr, tlb, 1); if (fault) { d_msg ("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--------------------------------------------------------------------------/*arm926ejs mmu_ops_t*/mmu_ops_t arm926ejs_mmu_ops = { arm926ejs_mmu_init, arm926ejs_mmu_exit, arm926ejs_mmu_read_byte, arm926ejs_mmu_write_byte, arm926ejs_mmu_read_halfword, arm926ejs_mmu_write_halfword, arm926ejs_mmu_read_word, arm926ejs_mmu_write_word, arm926ejs_mmu_load_instr, arm926ejs_mmu_mcr, arm926ejs_mmu_mrc,//teawater add for arm2x86 2005.06.19------------------------------------------- arm926ejs_mmu_v2p_dbct,//AJ2D--------------------------------------------------------------------------};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -