📄 op_helper.c.svn-base
字号:
if (size == 8) env->mxccregs[0] = ((uint64_t)T1 << 32) | T2; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, 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] = ((uint64_t)T1 << 32) | T2; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, 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] = ((uint64_t)T1 << 32) | T2; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); break; case 0x01c00a04: /* MXCC control register */ if (size == 4) env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | T1; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); break; case 0x01c00e00: /* MXCC error register */ // writing a 1 bit clears the error if (size == 8) env->mxccregs[6] &= ~(((uint64_t)T1 << 32) | T2); else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); break; case 0x01c00f00: /* MBus port address register */ if (size == 8) env->mxccregs[7] = ((uint64_t)T1 << 32) | T2; else DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); break; default: DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size); break; } DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi, size, T0, T1);#ifdef DEBUG_MXCC dump_mxcc(env);#endif break; case 3: /* MMU flush */ { int mmulev; mmulev = (T0 >> 8) & 15; DPRINTF_MMU("mmu flush level %d\n", mmulev); switch (mmulev) { case 0: // flush page tlb_flush_page(env, T0 & 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 = (T0 >> 8) & 0x1f; uint32_t oldreg; oldreg = env->mmuregs[reg]; switch(reg) { case 0: env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) | (T1 & 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 2: env->mmuregs[reg] = T1; 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: case 4: break; case 0x13: env->mmuregs[3] = T1; break; case 0x14: env->mmuregs[4] = T1; break; default: env->mmuregs[reg] = T1; 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(T0, T1); break; case 2: stw_user(T0 & ~1, T1); break; default: case 4: stl_user(T0 & ~3, T1); break; case 8: stq_user(T0 & ~7, ((uint64_t)T1 << 32) | T2); break; } break; case 0xb: /* Supervisor data access */ switch(size) { case 1: stb_kernel(T0, T1); break; case 2: stw_kernel(T0 & ~1, T1); break; default: case 4: stl_kernel(T0 & ~3, T1); break; case 8: stq_kernel(T0 & ~7, ((uint64_t)T1 << 32) | T2); 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 */ { // value (T1) = src // address (T0) = dst // copy 32 bytes unsigned int i; uint32_t src = T1 & ~3, dst = T0 & ~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 */ { // value (T1, T2) // address (T0) = dst // fill 32 bytes unsigned int i; uint32_t dst = T0 & 7; uint64_t val; val = (((uint64_t)T1) << 32) | T2; for (i = 0; i < 32; i += 8, dst += 8) stq_kernel(dst, val); } break; case 0x20: /* MMU passthrough */ { switch(size) { case 1: stb_phys(T0, T1); break; case 2: stw_phys(T0 & ~1, T1); break; case 4: default: stl_phys(T0 & ~3, T1); break; case 8: stq_phys(T0 & ~7, ((uint64_t)T1 << 32) | T2); break; } } break; case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ { switch(size) { case 1: stb_phys((target_phys_addr_t)T0 | ((target_phys_addr_t)(asi & 0xf) << 32), T1); break; case 2: stw_phys((target_phys_addr_t)(T0 & ~1) | ((target_phys_addr_t)(asi & 0xf) << 32), T1); break; case 4: default: stl_phys((target_phys_addr_t)(T0 & ~3) | ((target_phys_addr_t)(asi & 0xf) << 32), T1); break; case 8: stq_phys((target_phys_addr_t)(T0 & ~7) | ((target_phys_addr_t)(asi & 0xf) << 32), ((uint64_t)T1 << 32) | T2); 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(T0, 1, 0, asi); break; }#ifdef DEBUG_ASI dump_asi("write", T0, asi, size, T1, T2);#endif}#endif /* CONFIG_USER_ONLY */#else /* TARGET_SPARC64 */#ifdef CONFIG_USER_ONLYvoid helper_ld_asi(int asi, int size, int sign){ uint64_t ret = 0; if (asi < 0x80) raise_exception(TT_PRIV_ACT); 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(T0); break; case 2: ret = lduw_raw(T0 & ~1); break; case 4: ret = ldl_raw(T0 & ~3); break; default: case 8: ret = ldq_raw(T0 & ~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 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; } } T1 = ret;}void helper_st_asi(int asi, int size){ if (asi < 0x80) raise_exception(TT_PRIV_ACT); /* Convert to little endian */ switch (asi) { case 0x88: // Primary LE case 0x89: // Secondary LE switch(size) { case 2: T0 = bswap16(T0); break; case 4: T0 = bswap32(T0); break; case 8: T0 = bswap64(T0); break; default: break; } default: break; } switch(asi) { case 0x80: // Primary case 0x88: // Primary LE { switch(size) { case 1: stb_raw(T0, T1); break; case 2: stw_raw(T0 & ~1, T1); break; case 4: stl_raw(T0 & ~3, T1); break; case 8: default: stq_raw(T0 & ~7, T1); 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(T0, 1, 0, 1); return; }}#else /* CONFIG_USER_ONLY */void helper_ld_asi(int asi, int size, int sign){ uint64_t ret = 0; if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) raise_exception(TT_PRIV_ACT); 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(T0); break; case 2: ret = lduw_hypv(T0 & ~1); break; case 4: ret = ldl_hypv(T0 & ~3); break; default: case 8: ret = ldq_hypv(T0 & ~7); break; } } else { switch(size) { case 1: ret = ldub_kernel(T0); break; case 2: ret = lduw_kernel(T0 & ~1); break; case 4: ret = ldl_kernel(T0 & ~3); break; default: case 8: ret = ldq_kernel(T0 & ~7); break; } } } else { switch(size) { case 1: ret = ldub_user(T0); break; case 2: ret = lduw_user(T0 & ~1); break; case 4: ret = ldl_user(T0 & ~3); break; default: case 8: ret = ldq_user(T0 & ~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(T0); break; case 2: ret = lduw_phys(T0 & ~1); break; case 4: ret = ldl_phys(T0 & ~3); break; default: case 8: ret = ldq_phys(T0 & ~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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -