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

📄 helper.c.svn-base

📁 我们自己开发的一个OSEK操作系统!不知道可不可以?
💻 SVN-BASE
📖 第 1 页 / 共 4 页
字号:
extern int semihosting_enabled;/* Map CPU modes onto saved register banks.  */static inline int bank_number (int mode){    switch (mode) {    case ARM_CPU_MODE_USR:    case ARM_CPU_MODE_SYS:        return 0;    case ARM_CPU_MODE_SVC:        return 1;    case ARM_CPU_MODE_ABT:        return 2;    case ARM_CPU_MODE_UND:        return 3;    case ARM_CPU_MODE_IRQ:        return 4;    case ARM_CPU_MODE_FIQ:        return 5;    }    cpu_abort(cpu_single_env, "Bad mode %x\n", mode);    return -1;}void switch_mode(CPUState *env, int mode){    int old_mode;    int i;    old_mode = env->uncached_cpsr & CPSR_M;    if (mode == old_mode)        return;    if (old_mode == ARM_CPU_MODE_FIQ) {        memcpy (env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));        memcpy (env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));    } else if (mode == ARM_CPU_MODE_FIQ) {        memcpy (env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));        memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));    }    i = bank_number(old_mode);    env->banked_r13[i] = env->regs[13];    env->banked_r14[i] = env->regs[14];    env->banked_spsr[i] = env->spsr;    i = bank_number(mode);    env->regs[13] = env->banked_r13[i];    env->regs[14] = env->banked_r14[i];    env->spsr = env->banked_spsr[i];}static void v7m_push(CPUARMState *env, uint32_t val){    env->regs[13] -= 4;    stl_phys(env->regs[13], val);}static uint32_t v7m_pop(CPUARMState *env){    uint32_t val;    val = ldl_phys(env->regs[13]);    env->regs[13] += 4;    return val;}/* Switch to V7M main or process stack pointer.  */static void switch_v7m_sp(CPUARMState *env, int process){    uint32_t tmp;    if (env->v7m.current_sp != process) {        tmp = env->v7m.other_sp;        env->v7m.other_sp = env->regs[13];        env->regs[13] = tmp;        env->v7m.current_sp = process;    }}static void do_v7m_exception_exit(CPUARMState *env){    uint32_t type;    uint32_t xpsr;    type = env->regs[15];    if (env->v7m.exception != 0)        armv7m_nvic_complete_irq(env->v7m.nvic, env->v7m.exception);    /* Switch to the target stack.  */    switch_v7m_sp(env, (type & 4) != 0);    /* Pop registers.  */    env->regs[0] = v7m_pop(env);    env->regs[1] = v7m_pop(env);    env->regs[2] = v7m_pop(env);    env->regs[3] = v7m_pop(env);    env->regs[12] = v7m_pop(env);    env->regs[14] = v7m_pop(env);    env->regs[15] = v7m_pop(env);    xpsr = v7m_pop(env);    xpsr_write(env, xpsr, 0xfffffdff);    /* Undo stack alignment.  */    if (xpsr & 0x200)        env->regs[13] |= 4;    /* ??? The exception return type specifies Thread/Handler mode.  However       this is also implied by the xPSR value. Not sure what to do       if there is a mismatch.  */    /* ??? Likewise for mismatches between the CONTROL register and the stack       pointer.  */}void do_interrupt_v7m(CPUARMState *env){    uint32_t xpsr = xpsr_read(env);    uint32_t lr;    uint32_t addr;    lr = 0xfffffff1;    if (env->v7m.current_sp)        lr |= 4;    if (env->v7m.exception == 0)        lr |= 8;    /* For exceptions we just mark as pending on the NVIC, and let that       handle it.  */    /* TODO: Need to escalate if the current priority is higher than the       one we're raising.  */    switch (env->exception_index) {    case EXCP_UDEF:        armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_USAGE);        return;    case EXCP_SWI:        env->regs[15] += 2;        armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_SVC);        return;    case EXCP_PREFETCH_ABORT:    case EXCP_DATA_ABORT:        armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_MEM);        return;    case EXCP_BKPT:        if (semihosting_enabled) {            int nr;            nr = lduw_code(env->regs[15]) & 0xff;            if (nr == 0xab) {                env->regs[15] += 2;                env->regs[0] = do_arm_semihosting(env);                return;            }        }        armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_DEBUG);        return;    case EXCP_IRQ:        env->v7m.exception = armv7m_nvic_acknowledge_irq(env->v7m.nvic);        break;    case EXCP_EXCEPTION_EXIT:        do_v7m_exception_exit(env);        return;    default:        cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);        return; /* Never happens.  Keep compiler happy.  */    }    /* Align stack pointer.  */    /* ??? Should only do this if Configuration Control Register       STACKALIGN bit is set.  */    if (env->regs[13] & 4) {        env->regs[13] += 4;        xpsr |= 0x200;    }    /* Switch to the hander mode.  */    v7m_push(env, xpsr);    v7m_push(env, env->regs[15]);    v7m_push(env, env->regs[14]);    v7m_push(env, env->regs[12]);    v7m_push(env, env->regs[3]);    v7m_push(env, env->regs[2]);    v7m_push(env, env->regs[1]);    v7m_push(env, env->regs[0]);    switch_v7m_sp(env, 0);    env->uncached_cpsr &= ~CPSR_IT;    env->regs[14] = lr;    addr = ldl_phys(env->v7m.vecbase + env->v7m.exception * 4);    env->regs[15] = addr & 0xfffffffe;    env->thumb = addr & 1;}/* Handle a CPU exception.  */void do_interrupt(CPUARMState *env){    uint32_t addr;    uint32_t mask;    int new_mode;    uint32_t offset;    if (IS_M(env)) {        do_interrupt_v7m(env);        return;    }    /* TODO: Vectored interrupt controller.  */    switch (env->exception_index) {    case EXCP_UDEF:        new_mode = ARM_CPU_MODE_UND;        addr = 0x04;        mask = CPSR_I;        if (env->thumb)            offset = 2;        else            offset = 4;        break;    case EXCP_SWI:        if (semihosting_enabled) {            /* Check for semihosting interrupt.  */            if (env->thumb) {                mask = lduw_code(env->regs[15] - 2) & 0xff;            } else {                mask = ldl_code(env->regs[15] - 4) & 0xffffff;            }            /* Only intercept calls from privileged modes, to provide some               semblance of security.  */            if (((mask == 0x123456 && !env->thumb)                    || (mask == 0xab && env->thumb))                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {                env->regs[0] = do_arm_semihosting(env);                return;            }        }        new_mode = ARM_CPU_MODE_SVC;        addr = 0x08;        mask = CPSR_I;        /* The PC already points to the next instructon.  */        offset = 0;        break;    case EXCP_BKPT:        /* See if this is a semihosting syscall.  */        if (env->thumb && semihosting_enabled) {            mask = lduw_code(env->regs[15]) & 0xff;            if (mask == 0xab                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {                env->regs[15] += 2;                env->regs[0] = do_arm_semihosting(env);                return;            }        }        /* Fall through to prefetch abort.  */    case EXCP_PREFETCH_ABORT:        new_mode = ARM_CPU_MODE_ABT;        addr = 0x0c;        mask = CPSR_A | CPSR_I;        offset = 4;        break;    case EXCP_DATA_ABORT:        new_mode = ARM_CPU_MODE_ABT;        addr = 0x10;        mask = CPSR_A | CPSR_I;        offset = 8;        break;    case EXCP_IRQ:        new_mode = ARM_CPU_MODE_IRQ;        addr = 0x18;        /* Disable IRQ and imprecise data aborts.  */        mask = CPSR_A | CPSR_I;        offset = 4;        break;    case EXCP_FIQ:        new_mode = ARM_CPU_MODE_FIQ;        addr = 0x1c;        /* Disable FIQ, IRQ and imprecise data aborts.  */        mask = CPSR_A | CPSR_I | CPSR_F;        offset = 4;        break;    default:        cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);        return; /* Never happens.  Keep compiler happy.  */    }    /* High vectors.  */    if (env->cp15.c1_sys & (1 << 13)) {        addr += 0xffff0000;    }    switch_mode (env, new_mode);    env->spsr = cpsr_read(env);    /* Clear IT bits.  */    env->condexec_bits = 0;    /* Switch to the new mode, and switch to Arm mode.  */    /* ??? Thumb interrupt handlers not implemented.  */    env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;    env->uncached_cpsr |= mask;    env->thumb = 0;    env->regs[14] = env->regs[15] + offset;    env->regs[15] = addr;    env->interrupt_request |= CPU_INTERRUPT_EXITTB;}/* Check section/page access permissions.   Returns the page protection flags, or zero if the access is not   permitted.  */static inline int check_ap(CPUState *env, int ap, int domain, int access_type,                           int is_user){  int prot_ro;  if (domain == 3)    return PAGE_READ | PAGE_WRITE;  if (access_type == 1)      prot_ro = 0;  else      prot_ro = PAGE_READ;  switch (ap) {  case 0:      if (access_type == 1)          return 0;      switch ((env->cp15.c1_sys >> 8) & 3) {      case 1:          return is_user ? 0 : PAGE_READ;      case 2:          return PAGE_READ;      default:          return 0;      }  case 1:      return is_user ? 0 : PAGE_READ | PAGE_WRITE;  case 2:      if (is_user)          return prot_ro;      else          return PAGE_READ | PAGE_WRITE;  case 3:      return PAGE_READ | PAGE_WRITE;  case 4: case 7: /* Reserved.  */      return 0;  case 5:      return is_user ? 0 : prot_ro;  case 6:      return prot_ro;  default:      abort();  }}static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,			    int is_user, uint32_t *phys_ptr, int *prot){    int code;    uint32_t table;    uint32_t desc;    int type;    int ap;    int domain;    uint32_t phys_addr;    /* Pagetable walk.  */    /* Lookup l1 descriptor.  */    if (address & env->cp15.c2_mask)        table = env->cp15.c2_base1;    else        table = env->cp15.c2_base0;    table = (table & 0xffffc000) | ((address >> 18) & 0x3ffc);    desc = ldl_phys(table);    type = (desc & 3);    domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;    if (type == 0) {        /* Secton translation fault.  */        code = 5;        goto do_fault;    }    if (domain == 0 || domain == 2) {        if (type == 2)            code = 9; /* Section domain fault.  */        else            code = 11; /* Page domain fault.  */        goto do_fault;    }    if (type == 2) {        /* 1Mb section.  */        phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);        ap = (desc >> 10) & 3;        code = 13;    } else {        /* Lookup l2 entry.  */	if (type == 1) {	    /* Coarse pagetable.  */	    table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);	} else {	    /* Fine pagetable.  */	    table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);	}        desc = ldl_phys(table);        switch (desc & 3) {        case 0: /* Page translation fault.  */            code = 7;            goto do_fault;        case 1: /* 64k page.  */            phys_addr = (desc & 0xffff0000) | (address & 0xffff);            ap = (desc >> (4 + ((address >> 13) & 6))) & 3;            break;        case 2: /* 4k page.  */            phys_addr = (desc & 0xfffff000) | (address & 0xfff);            ap = (desc >> (4 + ((address >> 13) & 6))) & 3;            break;        case 3: /* 1k page.  */	    if (type == 1) {		if (arm_feature(env, ARM_FEATURE_XSCALE)) {		    phys_addr = (desc & 0xfffff000) | (address & 0xfff);		} else {		    /* Page translation fault.  */		    code = 7;		    goto do_fault;		}	    } else {		phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);	    }            ap = (desc >> 4) & 3;            break;        default:            /* Never happens, but compiler isn't smart enough to tell.  */            abort();        }        code = 15;    }    *prot = check_ap(env, ap, domain, access_type, is_user);    if (!*prot) {        /* Access permission fault.  */        goto do_fault;    }    *phys_ptr = phys_addr;    return 0;do_fault:    return code | (domain << 4);}static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,			    int is_user, uint32_t *phys_ptr, int *prot){    int code;    uint32_t table;    uint32_t desc;    uint32_t xn;    int type;    int ap;    int domain;    uint32_t phys_addr;    /* Pagetable walk.  */    /* Lookup l1 descriptor.  */    if (address & env->cp15.c2_mask)        table = env->cp15.c2_base1;    else        table = env->cp15.c2_base0;    table = (table & 0xffffc000) | ((address >> 18) & 0x3ffc);    desc = ldl_phys(table);    type = (desc & 3);    if (type == 0) {        /* Secton translation fault.  */        code = 5;        domain = 0;        goto do_fault;    } else if (type == 2 && (desc & (1 << 18))) {        /* Supersection.  */        domain = 0;    } else {        /* Section or page.  */        domain = (desc >> 4) & 0x1e;    }    domain = (env->cp15.c3 >> domain) & 3;    if (domain == 0 || domain == 2) {        if (type == 2)

⌨️ 快捷键说明

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