op_helper.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,373 行 · 第 1/5 页
C
2,373 行
switch(size) { case 2: ret = bswap16(ret); break; case 4: ret = bswap32(ret); break; case 8: ret = bswap64(ret); break; default: break; } default: break; } /* Convert to signed number */ if (sign) { switch(size) { case 1: ret = (int8_t) ret; break; case 2: ret = (int16_t) ret; break; case 4: ret = (int32_t) ret; break; default: break; } }#ifdef DEBUG_ASI dump_asi("read ", last_addr, asi, size, ret);#endif return ret;}void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size){#ifdef DEBUG_ASI dump_asi("write", addr, asi, size, val);#endif if (asi < 0x80) raise_exception(TT_PRIV_ACT); helper_check_align(addr, size - 1); ABI32_MASK(addr); /* Convert to little endian */ switch (asi) { case 0x88: // Primary LE case 0x89: // Secondary LE switch(size) { case 2: addr = bswap16(addr); break; case 4: addr = bswap32(addr); break; case 8: addr = bswap64(addr); break; default: break; } default: break; } switch(asi) { case 0x80: // Primary case 0x88: // Primary LE { switch(size) { case 1: stb_raw(addr, val); break; case 2: stw_raw(addr & ~1, val); break; case 4: stl_raw(addr & ~3, val); break; case 8: default: stq_raw(addr & ~7, val); break; } } break; case 0x81: // Secondary case 0x89: // Secondary LE // XXX return; case 0x82: // Primary no-fault, RO case 0x83: // Secondary no-fault, RO case 0x8a: // Primary no-fault LE, RO case 0x8b: // Secondary no-fault LE, RO default: do_unassigned_access(addr, 1, 0, 1); return; }}#else /* CONFIG_USER_ONLY */uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign){ uint64_t ret = 0;#if defined(DEBUG_ASI) target_ulong last_addr = addr;#endif if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) raise_exception(TT_PRIV_ACT); helper_check_align(addr, size - 1); switch (asi) { case 0x10: // As if user primary case 0x18: // As if user primary LE case 0x80: // Primary case 0x82: // Primary no-fault case 0x88: // Primary LE case 0x8a: // Primary no-fault LE if ((asi & 0x80) && (env->pstate & PS_PRIV)) { if (env->hpstate & HS_PRIV) { switch(size) { case 1: ret = ldub_hypv(addr); break; case 2: ret = lduw_hypv(addr & ~1); break; case 4: ret = ldl_hypv(addr & ~3); break; default: case 8: ret = ldq_hypv(addr & ~7); break; } } else { switch(size) { case 1: ret = ldub_kernel(addr); break; case 2: ret = lduw_kernel(addr & ~1); break; case 4: ret = ldl_kernel(addr & ~3); break; default: case 8: ret = ldq_kernel(addr & ~7); break; } } } else { switch(size) { case 1: ret = ldub_user(addr); break; case 2: ret = lduw_user(addr & ~1); break; case 4: ret = ldl_user(addr & ~3); break; default: case 8: ret = ldq_user(addr & ~7); break; } } break; case 0x14: // Bypass case 0x15: // Bypass, non-cacheable case 0x1c: // Bypass LE case 0x1d: // Bypass, non-cacheable LE { switch(size) { case 1: ret = ldub_phys(addr); break; case 2: ret = lduw_phys(addr & ~1); break; case 4: ret = ldl_phys(addr & ~3); break; default: case 8: ret = ldq_phys(addr & ~7); break; } break; } case 0x04: // Nucleus case 0x0c: // Nucleus Little Endian (LE) case 0x11: // As if user secondary case 0x19: // As if user secondary LE case 0x24: // Nucleus quad LDD 128 bit atomic case 0x2c: // Nucleus quad LDD 128 bit atomic case 0x4a: // UPA config case 0x81: // Secondary case 0x83: // Secondary no-fault case 0x89: // Secondary LE case 0x8b: // Secondary no-fault LE // XXX break; case 0x45: // LSU ret = env->lsu; break; case 0x50: // I-MMU regs { int reg = (addr >> 3) & 0xf; ret = env->immuregs[reg]; break; } case 0x51: // I-MMU 8k TSB pointer case 0x52: // I-MMU 64k TSB pointer case 0x55: // I-MMU data access // XXX break; case 0x56: // I-MMU tag read { unsigned int i; for (i = 0; i < 64; i++) { // Valid, ctx match, vaddr match if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 && env->itlb_tag[i] == addr) { ret = env->itlb_tag[i]; break; } } break; } case 0x58: // D-MMU regs { int reg = (addr >> 3) & 0xf; ret = env->dmmuregs[reg]; break; } case 0x5e: // D-MMU tag read { unsigned int i; for (i = 0; i < 64; i++) { // Valid, ctx match, vaddr match if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 && env->dtlb_tag[i] == addr) { ret = env->dtlb_tag[i]; break; } } break; } case 0x59: // D-MMU 8k TSB pointer case 0x5a: // D-MMU 64k TSB pointer case 0x5b: // D-MMU data pointer case 0x5d: // D-MMU data access case 0x48: // Interrupt dispatch, RO case 0x49: // Interrupt data receive case 0x7f: // Incoming interrupt vector, RO // XXX break; case 0x54: // I-MMU data in, WO case 0x57: // I-MMU demap, WO case 0x5c: // D-MMU data in, WO case 0x5f: // D-MMU demap, WO case 0x77: // Interrupt vector, WO default: do_unassigned_access(addr, 0, 0, 1); ret = 0; break; } /* Convert from little endian */ switch (asi) { case 0x0c: // Nucleus Little Endian (LE) case 0x18: // As if user primary LE case 0x19: // As if user secondary LE case 0x1c: // Bypass LE case 0x1d: // Bypass, non-cacheable LE case 0x88: // Primary LE case 0x89: // Secondary LE case 0x8a: // Primary no-fault LE case 0x8b: // Secondary no-fault LE switch(size) { case 2: ret = bswap16(ret); break; case 4: ret = bswap32(ret); break; case 8: ret = bswap64(ret); break; default: break; } default: break; } /* Convert to signed number */ if (sign) { switch(size) { case 1: ret = (int8_t) ret; break; case 2: ret = (int16_t) ret; break; case 4: ret = (int32_t) ret; break; default: break; } }#ifdef DEBUG_ASI dump_asi("read ", last_addr, asi, size, ret);#endif return ret;}void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size){#ifdef DEBUG_ASI dump_asi("write", addr, asi, size, val);#endif if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) raise_exception(TT_PRIV_ACT); helper_check_align(addr, size - 1); /* Convert to little endian */ switch (asi) { case 0x0c: // Nucleus Little Endian (LE) case 0x18: // As if user primary LE case 0x19: // As if user secondary LE case 0x1c: // Bypass LE case 0x1d: // Bypass, non-cacheable LE case 0x88: // Primary LE case 0x89: // Secondary LE switch(size) { case 2: addr = bswap16(addr); break; case 4: addr = bswap32(addr); break; case 8: addr = bswap64(addr); break; default: break; } default: break; } switch(asi) { case 0x10: // As if user primary case 0x18: // As if user primary LE case 0x80: // Primary case 0x88: // Primary LE if ((asi & 0x80) && (env->pstate & PS_PRIV)) { if (env->hpstate & HS_PRIV) { switch(size) { case 1: stb_hypv(addr, val); break; case 2: stw_hypv(addr & ~1, val); break; case 4: stl_hypv(addr & ~3, val); break; case 8: default: stq_hypv(addr & ~7, val); break; } } else { switch(size) { case 1: stb_kernel(addr, val); break; case 2: stw_kernel(addr & ~1, val); break; case 4: stl_kernel(addr & ~3, val); break; case 8: default: stq_kernel(addr & ~7, val); break; } } } else { switch(size) { case 1: stb_user(addr, val); break; case 2: stw_user(addr & ~1, val); break; case 4: stl_user(addr & ~3, val); break; case 8: default: stq_user(addr & ~7, val); break; } } break; case 0x14: // Bypass case 0x15: // Bypass, non-cacheable case 0x1c: // Bypass LE case 0x1d: // Bypass, non-cacheable LE { switch(size) { case 1: stb_phys(addr, val); break; case 2: stw_phys(addr & ~1, val); break; case 4: stl_phys(addr & ~3, val); break; case 8: default: stq_phys(addr & ~7, val); break; } } return; case 0x04: // Nucleus case 0x0c: // Nucleus Little Endian (LE) case 0x11: // As if user secondary case 0x19: // As if user secondary LE case 0x24: // Nucleus quad LDD 128 bit atomic case 0x2c: // Nucleus quad LDD 128 bit atomic case 0x4a: // UPA config case 0x81: // Secondary case 0x89: // Secondary LE // XXX return; case 0x45: // LSU { uint64_t oldreg; oldreg = env->lsu; env->lsu = val & (DMMU_E | IMMU_E); // Mappings generated during D/I MMU disabled mode are // invalid in normal mode if (oldreg != env->lsu) { DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);#ifdef DEBUG_MMU dump_mmu(env);#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?