op_helper.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,373 行 · 第 1/5 页
C
2,373 行
default: case 4: ret = ldl_user(addr & ~3); break; case 8: ret = ldq_user(addr & ~7); break; } break; case 0xb: /* Supervisor data access */ switch(size) { case 1: ret = ldub_kernel(addr); break; case 2: ret = lduw_kernel(addr & ~1); break; default: case 4: ret = ldl_kernel(addr & ~3); break; case 8: ret = ldq_kernel(addr & ~7); break; } break; case 0xc: /* I-cache tag */ case 0xd: /* I-cache data */ case 0xe: /* D-cache tag */ case 0xf: /* D-cache data */ break; case 0x20: /* MMU passthrough */ switch(size) { case 1: ret = ldub_phys(addr); break; case 2: ret = lduw_phys(addr & ~1); break; default: case 4: ret = ldl_phys(addr & ~3); break; case 8: ret = ldq_phys(addr & ~7); break; } break; case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ switch(size) { case 1: ret = ldub_phys((target_phys_addr_t)addr | ((target_phys_addr_t)(asi & 0xf) << 32)); break; case 2: ret = lduw_phys((target_phys_addr_t)(addr & ~1) | ((target_phys_addr_t)(asi & 0xf) << 32)); break; default: case 4: ret = ldl_phys((target_phys_addr_t)(addr & ~3) | ((target_phys_addr_t)(asi & 0xf) << 32)); break; case 8: ret = ldq_phys((target_phys_addr_t)(addr & ~7) | ((target_phys_addr_t)(asi & 0xf) << 32)); break; } break; case 0x30: // Turbosparc secondary cache diagnostic case 0x31: // Turbosparc RAM snoop case 0x32: // Turbosparc page table descriptor diagnostic case 0x39: /* data cache diagnostic register */ ret = 0; break; case 8: /* User code access, XXX */ default: do_unassigned_access(addr, 0, 0, asi); ret = 0; break; } 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, uint64_t val, int asi, int size){ helper_check_align(addr, size - 1); switch(asi) { case 2: /* SuperSparc MXCC registers */ switch (addr) { case 0x01c00000: /* MXCC stream data register 0 */ if (size == 8) env->mxccdata[0] = val; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00008: /* MXCC stream data register 1 */ if (size == 8) env->mxccdata[1] = val; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00010: /* MXCC stream data register 2 */ if (size == 8) env->mxccdata[2] = val; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00018: /* MXCC stream data register 3 */ if (size == 8) env->mxccdata[3] = val; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00100: /* MXCC stream source */ if (size == 8) env->mxccregs[0] = val; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 0); env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 8); env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16); env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24); break; case 0x01c00200: /* MXCC stream destination */ if (size == 8) env->mxccregs[1] = val; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0, env->mxccdata[0]); stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8, env->mxccdata[1]); stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]); stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]); break; case 0x01c00a00: /* MXCC control register */ if (size == 8) env->mxccregs[3] = val; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00a04: /* MXCC control register */ if (size == 4) env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | val; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00e00: /* MXCC error register */ // writing a 1 bit clears the error if (size == 8) env->mxccregs[6] &= ~val; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; case 0x01c00f00: /* MBus port address register */ if (size == 8) env->mxccregs[7] = val; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); break; default: DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size); break; } DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %08x\n", asi, size, addr, val);#ifdef DEBUG_MXCC dump_mxcc(env);#endif break; case 3: /* MMU flush */ { int mmulev; mmulev = (addr >> 8) & 15; DPRINTF_MMU("mmu flush level %d\n", mmulev); switch (mmulev) { case 0: // flush page tlb_flush_page(env, addr & 0xfffff000); break; case 1: // flush segment (256k) case 2: // flush region (16M) case 3: // flush context (4G) case 4: // flush entire tlb_flush(env, 1); break; default: break; }#ifdef DEBUG_MMU dump_mmu(env);#endif } break; case 4: /* write MMU regs */ { int reg = (addr >> 8) & 0x1f; uint32_t oldreg; oldreg = env->mmuregs[reg]; switch(reg) { case 0: // Control Register env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) | (val & 0x00ffffff); // Mappings generated during no-fault mode or MMU // disabled mode are invalid in normal mode if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) != (env->mmuregs[reg] & (MMU_E | MMU_NF | env->mmu_bm))) tlb_flush(env, 1); break; case 1: // Context Table Pointer Register env->mmuregs[reg] = val & env->mmu_ctpr_mask; break; case 2: // Context Register env->mmuregs[reg] = val & env->mmu_cxr_mask; if (oldreg != env->mmuregs[reg]) { /* we flush when the MMU context changes because QEMU has no MMU context support */ tlb_flush(env, 1); } break; case 3: // Synchronous Fault Status Register with Clear case 4: // Synchronous Fault Address Register break; case 0x10: // TLB Replacement Control Register env->mmuregs[reg] = val & env->mmu_trcr_mask; break; case 0x13: // Synchronous Fault Status Register with Read and Clear env->mmuregs[3] = val & env->mmu_sfsr_mask; break; case 0x14: // Synchronous Fault Address Register env->mmuregs[4] = val; break; default: env->mmuregs[reg] = val; break; } if (oldreg != env->mmuregs[reg]) { DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]); }#ifdef DEBUG_MMU dump_mmu(env);#endif } break; case 5: // Turbosparc ITLB Diagnostic case 6: // Turbosparc DTLB Diagnostic case 7: // Turbosparc IOTLB Diagnostic break; case 0xa: /* User data access */ switch(size) { case 1: stb_user(addr, val); break; case 2: stw_user(addr & ~1, val); break; default: case 4: stl_user(addr & ~3, val); break; case 8: stq_user(addr & ~7, val); break; } break; case 0xb: /* Supervisor data access */ switch(size) { case 1: stb_kernel(addr, val); break; case 2: stw_kernel(addr & ~1, val); break; default: case 4: stl_kernel(addr & ~3, val); break; case 8: stq_kernel(addr & ~7, val); break; } break; case 0xc: /* I-cache tag */ case 0xd: /* I-cache data */ case 0xe: /* D-cache tag */ case 0xf: /* D-cache data */ case 0x10: /* I/D-cache flush page */ case 0x11: /* I/D-cache flush segment */ case 0x12: /* I/D-cache flush region */ case 0x13: /* I/D-cache flush context */ case 0x14: /* I/D-cache flush user */ break; case 0x17: /* Block copy, sta access */ { // val = src // addr = dst // copy 32 bytes unsigned int i; uint32_t src = val & ~3, dst = addr & ~3, temp; for (i = 0; i < 32; i += 4, src += 4, dst += 4) { temp = ldl_kernel(src); stl_kernel(dst, temp); } } break; case 0x1f: /* Block fill, stda access */ { // addr = dst // fill 32 bytes with val unsigned int i; uint32_t dst = addr & 7; for (i = 0; i < 32; i += 8, dst += 8) stq_kernel(dst, val); } break; case 0x20: /* MMU passthrough */ { switch(size) { case 1: stb_phys(addr, val); break; case 2: stw_phys(addr & ~1, val); break; case 4: default: stl_phys(addr & ~3, val); break; case 8: stq_phys(addr & ~7, val); break; } } break; case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ { switch(size) { case 1: stb_phys((target_phys_addr_t)addr | ((target_phys_addr_t)(asi & 0xf) << 32), val); break; case 2: stw_phys((target_phys_addr_t)(addr & ~1) | ((target_phys_addr_t)(asi & 0xf) << 32), val); break; case 4: default: stl_phys((target_phys_addr_t)(addr & ~3) | ((target_phys_addr_t)(asi & 0xf) << 32), val); break; case 8: stq_phys((target_phys_addr_t)(addr & ~7) | ((target_phys_addr_t)(asi & 0xf) << 32), val); break; } } break; case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic case 0x31: // store buffer data, Ross RT620 I-cache flush or // Turbosparc snoop RAM case 0x32: // store buffer control or Turbosparc page table // descriptor diagnostic case 0x36: /* I-cache flash clear */ case 0x37: /* D-cache flash clear */ case 0x38: /* breakpoint diagnostics */ case 0x4c: /* breakpoint action */ break; case 8: /* User code access, XXX */ case 9: /* Supervisor code access, XXX */ default: do_unassigned_access(addr, 1, 0, asi); break; }#ifdef DEBUG_ASI dump_asi("write", addr, asi, size, val);#endif}#endif /* CONFIG_USER_ONLY */#else /* TARGET_SPARC64 */#ifdef CONFIG_USER_ONLYuint64_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) raise_exception(TT_PRIV_ACT); helper_check_align(addr, size - 1); ABI32_MASK(addr); switch (asi) { case 0x80: // Primary case 0x82: // Primary no-fault case 0x88: // Primary LE case 0x8a: // Primary no-fault LE { switch(size) { case 1: ret = ldub_raw(addr); break; case 2: ret = lduw_raw(addr & ~1); break; case 4: ret = ldl_raw(addr & ~3); break; default: case 8: ret = ldq_raw(addr & ~7); break; } } break; case 0x81: // Secondary case 0x83: // Secondary no-fault case 0x89: // Secondary LE case 0x8b: // Secondary no-fault LE // XXX break; default: break; } /* Convert from little endian */ switch (asi) { case 0x88: // Primary LE case 0x89: // Secondary LE case 0x8a: // Primary no-fault LE case 0x8b: // Secondary no-fault LE
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?