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

📄 ppc32.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Cisco router simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * PowerPC (32-bit) generic routines. */#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 <assert.h>#include "rbtree.h"#include "cpu.h"#include "dynamips.h"#include "memory.h"#include "device.h"#include "ppc32_mem.h"#include "ppc32_exec.h"#include "ppc32_jit.h"/* Reset a PowerPC CPU */int ppc32_reset(cpu_ppc_t *cpu){   cpu->ia = PPC32_ROM_START;   cpu->gpr[1] = PPC32_ROM_SP;   cpu->msr = PPC32_MSR_IP;   /* Restart the MTS subsystem */   ppc32_mem_restart(cpu);   /* Flush JIT structures */   ppc32_jit_flush(cpu,0);   return(0);}/* Initialize a PowerPC processor */int ppc32_init(cpu_ppc_t *cpu){   /* Initialize JIT operations */   jit_op_init_cpu(cpu->gen);   /* Initialize idle timer */   cpu->gen->idle_max = 1500;   cpu->gen->idle_sleep_time = 30000;   /* Timer IRQ parameters (default frequency: 250 Hz <=> 4ms period) */   cpu->timer_irq_check_itv = 1000;   cpu->timer_irq_freq      = 250;   /* Enable/disable direct block jump */   cpu->exec_blk_direct_jump = cpu->vm->exec_blk_direct_jump;   /* Idle loop mutex and condition */   pthread_mutex_init(&cpu->gen->idle_mutex,NULL);   pthread_cond_init(&cpu->gen->idle_cond,NULL);   /* Set the CPU methods */   cpu->gen->reg_set =  (void *)ppc32_reg_set;   cpu->gen->reg_dump = (void *)ppc32_dump_regs;   cpu->gen->mmu_dump = (void *)ppc32_dump_mmu;   cpu->gen->mmu_raw_dump = (void *)ppc32_dump_mmu;   cpu->gen->add_breakpoint = (void *)ppc32_add_breakpoint;   cpu->gen->remove_breakpoint = (void *)ppc32_remove_breakpoint;   cpu->gen->set_idle_pc = (void *)ppc32_set_idle_pc;   cpu->gen->get_idling_pc = (void *)ppc32_get_idling_pc;   /* zzz */   memset(cpu->vtlb,0xFF,sizeof(cpu->vtlb));   /* Set the startup parameters */   ppc32_reset(cpu);   return(0);}/* Delete a PowerPC processor */void ppc32_delete(cpu_ppc_t *cpu){   if (cpu) {      ppc32_mem_shutdown(cpu);      ppc32_jit_shutdown(cpu);   }}/* Set the processor version register (PVR) */void ppc32_set_pvr(cpu_ppc_t *cpu,m_uint32_t pvr){   cpu->pvr = pvr;   ppc32_mem_restart(cpu);}/* Set idle PC value */void ppc32_set_idle_pc(cpu_gen_t *cpu,m_uint64_t addr){   CPU_PPC32(cpu)->idle_pc = (m_uint32_t)addr;}/* Timer IRQ */void *ppc32_timer_irq_run(cpu_ppc_t *cpu){   pthread_mutex_t umutex = PTHREAD_MUTEX_INITIALIZER;   pthread_cond_t ucond = PTHREAD_COND_INITIALIZER;   struct timespec t_spc;   m_tmcnt_t expire;   u_int interval;   u_int threshold;#if 0   while(!cpu->timer_irq_armed)      sleep(1);#endif   interval = 1000000 / cpu->timer_irq_freq;   threshold = cpu->timer_irq_freq * 10;   expire = m_gettime_usec() + interval;   while(cpu->gen->state != CPU_STATE_HALTED) {      pthread_mutex_lock(&umutex);      t_spc.tv_sec = expire / 1000000;      t_spc.tv_nsec = (expire % 1000000) * 1000;      pthread_cond_timedwait(&ucond,&umutex,&t_spc);      pthread_mutex_unlock(&umutex);      if (likely(!cpu->irq_disable) &&          likely(cpu->gen->state == CPU_STATE_RUNNING) &&          likely(cpu->msr & PPC32_MSR_EE))      {         cpu->timer_irq_pending++;         if (unlikely(cpu->timer_irq_pending > threshold)) {            cpu->timer_irq_pending = 0;            cpu->timer_drift++;#if 0            printf("Timer IRQ not accurate (%u pending IRQ): "                   "reduce the \"--timer-irq-check-itv\" parameter "                   "(current value: %u)\n",                   cpu->timer_irq_pending,cpu->timer_irq_check_itv);#endif         }      }      expire += interval;   }   return NULL;}#define IDLE_HASH_SIZE  8192/* Idle PC hash item */struct ppc32_idle_pc_hash {   m_uint32_t ia;   u_int count;   struct ppc32_idle_pc_hash *next;};/* Determine an "idling" PC */int ppc32_get_idling_pc(cpu_gen_t *cpu){   cpu_ppc_t *pcpu = CPU_PPC32(cpu);   struct ppc32_idle_pc_hash **pc_hash,*p;   struct cpu_idle_pc *res;   u_int h_index,res_count;   m_uint32_t cur_ia;   int i;   cpu->idle_pc_prop_count = 0;   if (pcpu->idle_pc != 0) {      printf("\nYou already use an idle PC, using the calibration would give "             "incorrect results.\n");      return(-1);   }   printf("\nPlease wait while gathering statistics...\n");   pc_hash = calloc(IDLE_HASH_SIZE,sizeof(struct ppc32_idle_pc_hash *));   /* Disable IRQ */   pcpu->irq_disable = TRUE;   /* Take 1000 measures, each mesure every 10ms */   for(i=0;i<1000;i++) {      cur_ia = pcpu->ia;      h_index = (cur_ia >> 2) & (IDLE_HASH_SIZE-1);      for(p=pc_hash[h_index];p;p=p->next)         if (p->ia == cur_ia) {            p->count++;            break;         }      if (!p) {         if ((p = malloc(sizeof(*p)))) {            p->ia    = cur_ia;            p->count = 1;            p->next  = pc_hash[h_index];            pc_hash[h_index] = p;         }      }      usleep(10000);   }   /* Select PCs */   for(i=0,res_count=0;i<IDLE_HASH_SIZE;i++) {      for(p=pc_hash[i];p;p=p->next)         if ((p->count >= 20) && (p->count <= 80)) {            res = &cpu->idle_pc_prop[cpu->idle_pc_prop_count++];            res->pc    = p->ia;            res->count = p->count;            if (cpu->idle_pc_prop_count >= CPU_IDLE_PC_MAX_RES)               goto done;         }   } done:   /* Set idle PC */   if (cpu->idle_pc_prop_count) {      printf("Done. Suggested idling PC:\n");      for(i=0;i<cpu->idle_pc_prop_count;i++) {         printf("   0x%llx (count=%u)\n",                cpu->idle_pc_prop[i].pc,                cpu->idle_pc_prop[i].count);      }               printf("Restart the emulator with \"--idle-pc=0x%llx\" (for example)\n",             cpu->idle_pc_prop[0].pc);   } else {      printf("Done. No suggestion for idling PC, dumping the full table:\n");      for(i=0;i<IDLE_HASH_SIZE;i++)         for(p=pc_hash[i];p;p=p->next) {            printf("  0x%8.8x (%3u)\n",p->ia,p->count);            if (cpu->idle_pc_prop_count < CPU_IDLE_PC_MAX_RES) {               res = &cpu->idle_pc_prop[cpu->idle_pc_prop_count++];               res->pc    = p->ia;               res->count = p->count;            }         }             printf("\n");   }   /* Re-enable IRQ */   pcpu->irq_disable = FALSE;   return(0);}#if 0/* Set an IRQ (VM IRQ standard routing) */void ppc32_vm_set_irq(vm_instance_t *vm,u_int irq){   cpu_ppc_t *boot_cpu;   boot_cpu = CPU_PPC32(vm->boot_cpu);   if (boot_cpu->irq_disable) {      boot_cpu->irq_pending = 0;      return;   }   ppc32_set_irq(boot_cpu,irq);   if (boot_cpu->irq_idle_preempt[irq])      cpu_idle_break_wait(vm->boot_cpu);}/* Clear an IRQ (VM IRQ standard routing) */void ppc32_vm_clear_irq(vm_instance_t *vm,u_int irq){   cpu_ppc_t *boot_cpu;   boot_cpu = CPU_PPC32(vm->boot_cpu);   ppc32_clear_irq(boot_cpu,irq);}#endif/* Generate an exception */void ppc32_trigger_exception(cpu_ppc_t *cpu,u_int exc_vector){   //printf("TRIGGER_EXCEPTION: saving cpu->ia=0x%8.8x, msr=0x%8.8x\n",   //       cpu->ia,cpu->msr);   /* Save the return instruction address */   cpu->srr0 = cpu->ia;      if (exc_vector == PPC32_EXC_SYSCALL)      cpu->srr0 += sizeof(ppc_insn_t);   //printf("SRR0 = 0x%8.8x\n",cpu->srr0);   /* Save Machine State Register (MSR) */   cpu->srr1 = cpu->msr & PPC32_EXC_SRR1_MASK;   //printf("SRR1 = 0x%8.8x\n",cpu->srr1);   /* Set the new SRR value */   cpu->msr &= ~PPC32_EXC_MSR_MASK;   cpu->irq_check = FALSE;   //printf("MSR = 0x%8.8x\n",cpu->msr);   /* Use bootstrap vectors ? */   if (cpu->msr & PPC32_MSR_IP)      cpu->ia = 0xFFF00000 + exc_vector;   else      cpu->ia = exc_vector;}/* Trigger IRQs */fastcall void ppc32_trigger_irq(cpu_ppc_t *cpu){   if (unlikely(cpu->irq_disable)) {

⌨️ 快捷键说明

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