⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cp0.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Cisco 7200 (Predator) simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * MIPS Coprocessor 0 (System Coprocessor) implementation. * We don't use the JIT here, since there is no high performance needed. */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/mman.h>#include <fcntl.h>#include "rbtree.h"#include "mips64.h"#include "dynamips.h"#include "memory.h"#include "device.h"#include "cp0.h"/* MIPS cp0 registers names */char *mips64_cp0_reg_names[MIPS64_CP0_REG_NR] = {   "index" ,    "random",    "entry_lo0",    "entry_lo1",    "context",    "pagemask",   "wired",    "info",   "badvaddr",    "count",    "entry_hi",    "compare",    "status",    "cause",   "epc",    "prid",    "config",    "ll_addr",    "watch_lo",    "watch_hi",    "xcontext",   "cp0_r21",   "cp0_r22",   "cp0_r23",   "cp0_r24",   "cp0_r25",   "ecc",    "cache_err",    "tag_lo",    "tag_hi",    "err_epc",   "cp0_r31",};/* Get cp0 register index given its name */int cp0_get_reg_index(char *name){   int i;   for(i=0;i<MIPS64_CP0_REG_NR;i++)      if (!strcmp(mips64_cp0_reg_names[i],name))         return(i);   return(-1);}/* Get the CPU operating mode (User,Supervisor or Kernel) - inline version */static forced_inline u_int cp0_get_mode_inline(cpu_mips_t *cpu){     mips_cp0_t *cp0 = &cpu->cp0;   u_int cpu_mode;   cpu_mode = cp0->reg[MIPS_CP0_STATUS] >> MIPS_CP0_STATUS_KSU_SHIFT;   cpu_mode &= MIPS_CP0_STATUS_KSU_MASK;   return(cpu_mode);}/* Get the CPU operating mode (User,Supervisor or Kernel) */u_int cp0_get_mode(cpu_mips_t *cpu){     return(cp0_get_mode_inline(cpu));}/* Check that we are running in kernel mode */int cp0_check_kernel_mode(cpu_mips_t *cpu){   u_int cpu_mode;   cpu_mode = cp0_get_mode(cpu);   if (cpu_mode != MIPS_CP0_STATUS_KM) {      /* XXX Branch delay slot */      mips64_trigger_exception(cpu,MIPS_CP0_CAUSE_ILLOP,0);      return(1);   }   return(0);}/* Get value of random register */static inline u_int cp0_get_random_reg(cpu_mips_t *cpu){   u_int wired;   /* We use the virtual count register as a basic "random" value */   wired = cpu->cp0.reg[MIPS_CP0_WIRED];   return(wired + (cpu->cp0_virt_cnt_reg % (cpu->cp0.tlb_entries - wired)));}/* Get a cp0 register (fast version) */static inline m_uint64_t cp0_get_reg_fast(cpu_mips_t *cpu,u_int cp0_reg){   mips_cp0_t *cp0 = &cpu->cp0;   m_uint32_t delta,res;   switch(cp0_reg) {      case MIPS_CP0_COUNT:         delta = cpu->cp0_virt_cmp_reg - cpu->cp0_virt_cnt_reg;         res = (m_uint32_t)cp0->reg[MIPS_CP0_COMPARE];         res -= cpu->vm->clock_divisor * delta;         return(sign_extend(res,32));#if 1      case MIPS_CP0_COMPARE:         return(sign_extend(cp0->reg[MIPS_CP0_COMPARE],32));#else      /* really useful and logical ? */      case MIPS_CP0_COMPARE:         delta = cpu->cp0_virt_cmp_reg - cpu->cp0_virt_cnt_reg;         res = (m_uint32_t)cp0->reg[MIPS_CP0_COUNT];         res += (cpu->vm->clock_divisor * delta);         return(res);#endif      case MIPS_CP0_INFO:         return(MIPS64_R7000_TLB64_ENABLE);      case MIPS_CP0_RANDOM:                 return(cp0_get_random_reg(cpu));      default:         return(cp0->reg[cp0_reg]);   }}/* Get a cp0 register */m_uint64_t cp0_get_reg(cpu_mips_t *cpu,u_int cp0_reg){   return(cp0_get_reg_fast(cpu,cp0_reg));}/* Set a cp0 register */static inline void cp0_set_reg(cpu_mips_t *cpu,u_int cp0_reg,m_uint64_t val){   mips_cp0_t *cp0 = &cpu->cp0;   m_uint32_t delta;   switch(cp0_reg) {      case MIPS_CP0_STATUS:      case MIPS_CP0_CAUSE:         cp0->reg[cp0_reg] = val;         mips64_update_irq_flag(cpu);         break;               case MIPS_CP0_PAGEMASK:         cp0->reg[cp0_reg] = val & MIPS_TLB_PAGE_MASK;         break;               case MIPS_CP0_COMPARE:         mips64_clear_irq(cpu,7);         mips64_update_irq_flag(cpu);         cp0->reg[cp0_reg] = val;         delta = val - cp0->reg[MIPS_CP0_COUNT];         cpu->cp0_virt_cnt_reg = 0;         cpu->cp0_virt_cmp_reg = delta / cpu->vm->clock_divisor;         break;      case MIPS_CP0_COUNT:         cp0->reg[cp0_reg] = val;         delta = cp0->reg[MIPS_CP0_COMPARE] - val;         cpu->cp0_virt_cnt_reg = 0;         cpu->cp0_virt_cmp_reg = delta / cpu->vm->clock_divisor;         break;     case MIPS_CP0_TLB_HI:         cp0->reg[cp0_reg] = val & MIPS_CP0_HI_SAFE_MASK;         break;      case MIPS_CP0_TLB_LO_0:      case MIPS_CP0_TLB_LO_1:         cp0->reg[cp0_reg] = val & MIPS_CP0_LO_SAFE_MASK;         break;      case MIPS_CP0_RANDOM:      case MIPS_CP0_PRID:      case MIPS_CP0_CONFIG:         /* read only registers */         break;      case MIPS_CP0_WIRED:         cp0->reg[cp0_reg] = val & MIPS64_TLB_IDX_MASK;         break;      default:         cp0->reg[cp0_reg] = val;   }}/* Get a cp0 "set 1" register (R7000) */m_uint64_t cp0_s1_get_reg(cpu_mips_t *cpu,u_int cp0_s1_reg){   switch(cp0_s1_reg) {      case MIPS_CP0_S1_CONFIG:         return(0x7F << 25);      case MIPS_CP0_S1_IPLLO:         return(cpu->cp0.ipl_lo);      case MIPS_CP0_S1_IPLHI:         return(cpu->cp0.ipl_hi);      case MIPS_CP0_S1_INTCTL:         return(cpu->cp0.int_ctl);      case MIPS_CP0_S1_DERRADDR0:         return(cpu->cp0.derraddr0);      case MIPS_CP0_S1_DERRADDR1:         return(cpu->cp0.derraddr1);      default:         /* undefined register */         cpu_log(cpu,"CP0_S1","trying to read unknown register %u\n",                 cp0_s1_reg);         return(0);   }}/* Set a cp0 "set 1" register (R7000) */static inline void cp0_s1_set_reg(cpu_mips_t *cpu,u_int cp0_s1_reg,                                  m_uint64_t val){   mips_cp0_t *cp0 = &cpu->cp0;   switch(cp0_s1_reg) {      case MIPS_CP0_S1_IPLLO:         cp0->ipl_lo = val;         break;      case MIPS_CP0_S1_IPLHI:         cp0->ipl_hi = val;         break;      case MIPS_CP0_S1_INTCTL:         cp0->int_ctl = val;         break;      case MIPS_CP0_S1_DERRADDR0:         cp0->derraddr0 = val;         break;               case MIPS_CP0_S1_DERRADDR1:         cp0->derraddr1 = val;         break;      default:         cpu_log(cpu,"CP0_S1","trying to set unknown register %u (val=0x%x)\n",                 cp0_s1_reg,val);   }}/* DMFC0 */fastcall void cp0_exec_dmfc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg){   cpu->gpr[gp_reg] = cp0_get_reg_fast(cpu,cp0_reg);}/* DMTC0 */fastcall void cp0_exec_dmtc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg){   cp0_set_reg(cpu,cp0_reg,cpu->gpr[gp_reg]);}/* MFC0 */fastcall void cp0_exec_mfc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg){   cpu->gpr[gp_reg] = sign_extend(cp0_get_reg_fast(cpu,cp0_reg),32);}/* MTC0 */fastcall void cp0_exec_mtc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg){   cp0_set_reg(cpu,cp0_reg,cpu->gpr[gp_reg] & 0xffffffff);}/* CFC0 */fastcall void cp0_exec_cfc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg){   cpu->gpr[gp_reg] = sign_extend(cp0_s1_get_reg(cpu,cp0_reg),32);}/* CTC0 */fastcall void cp0_exec_ctc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg){   cp0_s1_set_reg(cpu,cp0_reg,cpu->gpr[gp_reg] & 0xffffffff);}/* Get the page size corresponding to a page mask */static inline m_uint32_t get_page_size(m_uint32_t page_mask){   return((page_mask + 0x2000) >> 1);}/* Write page size in buffer */static char *get_page_size_str(char *buffer,size_t len,m_uint32_t page_mask){   m_uint32_t page_size;   page_size = get_page_size(page_mask);      /* Mb ? */   if (page_size >= (1024*1024))      snprintf(buffer,len,"%uMB",page_size >> 20);   else      snprintf(buffer,len,"%uKB",page_size >> 10);   return buffer;}/* Get the VPN2 mask */static forced_inline m_uint64_t cp0_get_vpn2_mask(cpu_mips_t *cpu){   if (cpu->addr_mode == 64)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -