📄 op_helper.c
字号:
#include "exec.h"//#define DEBUG_PCALL//#define DEBUG_MMUvoid raise_exception(int tt){ env->exception_index = tt; cpu_loop_exit();} #ifdef USE_INT_TO_FLOAT_HELPERSvoid do_fitos(void){ FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);}void do_fitod(void){ DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);}#endifvoid do_fabss(void){ FT0 = float32_abs(FT1);}#ifdef TARGET_SPARC64void do_fabsd(void){ DT0 = float64_abs(DT1);}#endifvoid do_fsqrts(void){ FT0 = float32_sqrt(FT1, &env->fp_status);}void do_fsqrtd(void){ DT0 = float64_sqrt(DT1, &env->fp_status);}#define GEN_FCMP(name, size, reg1, reg2, FS) \ void glue(do_, name) (void) \ { \ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \ case float_relation_unordered: \ T0 = (FSR_FCC1 | FSR_FCC0) << FS; \ if (env->fsr & FSR_NVM) { \ env->fsr |= T0; \ raise_exception(TT_FP_EXCP); \ } else { \ env->fsr |= FSR_NVA; \ } \ break; \ case float_relation_less: \ T0 = FSR_FCC0 << FS; \ break; \ case float_relation_greater: \ T0 = FSR_FCC1 << FS; \ break; \ default: \ T0 = 0; \ break; \ } \ env->fsr |= T0; \ }GEN_FCMP(fcmps, float32, FT0, FT1, 0);GEN_FCMP(fcmpd, float64, DT0, DT1, 0);#ifdef TARGET_SPARC64GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22);GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22);GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24);GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24);GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26);GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26);#endif#if defined(CONFIG_USER_ONLY) void helper_ld_asi(int asi, int size, int sign){}void helper_st_asi(int asi, int size, int sign){}#else#ifndef TARGET_SPARC64void helper_ld_asi(int asi, int size, int sign){ uint32_t ret = 0; switch (asi) { case 3: /* MMU probe */ { int mmulev; mmulev = (T0 >> 8) & 15; if (mmulev > 4) ret = 0; else { ret = mmu_probe(env, T0, mmulev); //bswap32s(&ret); }#ifdef DEBUG_MMU printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);#endif } break; case 4: /* read MMU regs */ { int reg = (T0 >> 8) & 0xf; ret = env->mmuregs[reg]; if (reg == 3) /* Fault status cleared on read */ env->mmuregs[reg] = 0;#ifdef DEBUG_MMU printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret);#endif } break; case 0x20 ... 0x2f: /* MMU passthrough */ switch(size) { case 1: ret = ldub_phys(T0); break; case 2: ret = lduw_phys(T0 & ~1); break; default: case 4: ret = ldl_phys(T0 & ~3); break; case 8: ret = ldl_phys(T0 & ~3); T0 = ldl_phys((T0 + 4) & ~3); break; } break; default: ret = 0; break; } T1 = ret;}void helper_st_asi(int asi, int size, int sign){ switch(asi) { case 3: /* MMU flush */ { int mmulev; mmulev = (T0 >> 8) & 15;#ifdef DEBUG_MMU printf("mmu flush level %d\n", mmulev);#endif 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 return; } case 4: /* write MMU regs */ { int reg = (T0 >> 8) & 0xf; uint32_t oldreg; oldreg = env->mmuregs[reg]; switch(reg) { case 0: env->mmuregs[reg] &= ~(MMU_E | MMU_NF); env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF); // Mappings generated during no-fault mode or MMU // disabled mode are invalid in normal mode if (oldreg != env->mmuregs[reg]) 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; default: env->mmuregs[reg] = T1; break; }#ifdef DEBUG_MMU if (oldreg != env->mmuregs[reg]) { printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]); } dump_mmu(env);#endif return; } case 0x17: /* Block copy, sta access */ { // value (T1) = src // address (T0) = dst // copy 32 bytes uint32_t src = T1, dst = T0; uint8_t temp[32]; tswap32s(&src); cpu_physical_memory_read(src, (void *) &temp, 32); cpu_physical_memory_write(dst, (void *) &temp, 32); } return; case 0x1f: /* Block fill, stda access */ { // value (T1, T2) // address (T0) = dst // fill 32 bytes int i; uint32_t dst = T0; uint64_t val; val = (((uint64_t)T1) << 32) | T2; tswap64s(&val); for (i = 0; i < 32; i += 8, dst += 8) { cpu_physical_memory_write(dst, (void *) &val, 8); } } return; case 0x20 ... 0x2f: /* 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: stl_phys(T0 & ~3, T1); stl_phys((T0 + 4) & ~3, T2); break; } } return; default: return; }}#elsevoid helper_ld_asi(int asi, int size, int sign){ uint64_t ret = 0; if (asi < 0x80 && (env->pstate & PS_PRIV) == 0) raise_exception(TT_PRIV_ACT); switch (asi) { case 0x14: // Bypass case 0x15: // Bypass, non-cacheable { 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 0x10: // As if user primary case 0x11: // As if user secondary 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 0x24: // Nucleus quad LDD 128 bit atomic case 0x2c: // Nucleus quad LDD 128 bit atomic case 0x4a: // UPA config case 0x82: // Primary no-fault case 0x83: // Secondary no-fault case 0x88: // Primary LE case 0x89: // Secondary LE case 0x8a: // Primary no-fault LE case 0x8b: // Secondary no-fault LE // XXX break; case 0x45: // LSU ret = env->lsu; break; case 0x50: // I-MMU regs { int reg = (T0 >> 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] == T0) { ret = env->itlb_tag[i]; break; } } break; } case 0x58: // D-MMU regs { int reg = (T0 >> 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] == T0) { 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: ret = 0; break; } T1 = ret;}void helper_st_asi(int asi, int size, int sign){ if (asi < 0x80 && (env->pstate & PS_PRIV) == 0) raise_exception(TT_PRIV_ACT); switch(asi) { case 0x14: // Bypass case 0x15: // Bypass, non-cacheable { switch(size) { case 1: stb_phys(T0, T1); break; case 2: stw_phys(T0 & ~1, T1); break; case 4: stl_phys(T0 & ~3, T1); break; case 8: default: stq_phys(T0 & ~7, T1); break; } } return; case 0x04: // Nucleus case 0x0c: // Nucleus Little Endian (LE) case 0x10: // As if user primary case 0x11: // As if user secondary 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 0x24: // Nucleus quad LDD 128 bit atomic case 0x2c: // Nucleus quad LDD 128 bit atomic case 0x4a: // UPA config case 0x88: // Primary LE case 0x89: // Secondary LE // XXX return; case 0x45: // LSU { uint64_t oldreg; oldreg = env->lsu; env->lsu = T1 & (DMMU_E | IMMU_E); // Mappings generated during D/I MMU disabled mode are // invalid in normal mode if (oldreg != env->lsu) {#ifdef DEBUG_MMU printf("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu); dump_mmu(env);#endif tlb_flush(env, 1); } return; } case 0x50: // I-MMU regs { int reg = (T0 >> 3) & 0xf; uint64_t oldreg;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -