📄 op.c
字号:
RETURN();}void op_mtc0_datalo (void){ env->CP0_DataLo = T0; /* XXX */ RETURN();}void op_mtc0_taghi (void){ env->CP0_TagHi = T0; /* XXX */ RETURN();}void op_mtc0_datahi (void){ env->CP0_DataHi = T0; /* XXX */ RETURN();}void op_mtc0_errorepc (void){ env->CP0_ErrorEPC = (int32_t)T0; RETURN();}void op_mtc0_desave (void){ env->CP0_DESAVE = T0; RETURN();}void op_dmfc0_entrylo0 (void){ T0 = env->CP0_EntryLo0; RETURN();}void op_dmfc0_entrylo1 (void){ T0 = env->CP0_EntryLo1; RETURN();}void op_dmfc0_context (void){ T0 = env->CP0_Context; RETURN();}void op_dmfc0_badvaddr (void){ T0 = env->CP0_BadVAddr; RETURN();}void op_dmfc0_entryhi (void){ T0 = env->CP0_EntryHi; RETURN();}void op_dmfc0_epc (void){ T0 = env->CP0_EPC; RETURN();}void op_dmfc0_lladdr (void){ T0 = env->CP0_LLAddr >> 4; RETURN();}void op_dmfc0_watchlo0 (void){ T0 = env->CP0_WatchLo; RETURN();}void op_dmfc0_xcontext (void){ T0 = env->CP0_XContext; RETURN();}void op_dmfc0_depc (void){ T0 = env->CP0_DEPC; RETURN();}void op_dmfc0_errorepc (void){ T0 = env->CP0_ErrorEPC; RETURN();}void op_dmtc0_entrylo0 (void){ /* Large physaddr not implemented */ /* 1k pages not implemented */ env->CP0_EntryLo0 = T0 & 0x3FFFFFFF; RETURN();}void op_dmtc0_entrylo1 (void){ /* Large physaddr not implemented */ /* 1k pages not implemented */ env->CP0_EntryLo1 = T0 & 0x3FFFFFFF; RETURN();}void op_dmtc0_context (void){ env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0); RETURN();}void op_dmtc0_epc (void){ env->CP0_EPC = T0; RETURN();}void op_dmtc0_watchlo0 (void){ env->CP0_WatchLo = T0; RETURN();}void op_dmtc0_xcontext (void){ env->CP0_XContext = T0; /* XXX */ RETURN();}void op_dmtc0_depc (void){ env->CP0_DEPC = T0; RETURN();}void op_dmtc0_errorepc (void){ env->CP0_ErrorEPC = T0; RETURN();}#ifdef MIPS_USES_FPU#if 0# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)#else# define DEBUG_FPU_STATE() do { } while(0)#endifvoid op_cp1_enabled(void){ if (!(env->CP0_Status & (1 << CP0St_CU1))) { CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1); } RETURN();}/* CP1 functions */void op_cfc1 (void){ if (T1 == 0) { T0 = env->fcr0; } else { /* fetch fcr31, masking unused bits */ T0 = env->fcr31 & 0x0183FFFF; } DEBUG_FPU_STATE(); RETURN();}/* convert MIPS rounding mode in FCR31 to IEEE library */unsigned int ieee_rm[] = { float_round_nearest_even, float_round_to_zero, float_round_up, float_round_down};#define RESTORE_ROUNDING_MODE \ set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)void op_ctc1 (void){ if (T1 == 0) { /* XXX should this throw an exception? * don't write to FCR0. * env->fcr0 = T0; */ } else { /* store new fcr31, masking unused bits */ env->fcr31 = T0 & 0x0183FFFF; /* set rounding mode */ RESTORE_ROUNDING_MODE;#ifndef CONFIG_SOFTFLOAT /* no floating point exception for native float */ SET_FP_ENABLE(env->fcr31, 0);#endif } DEBUG_FPU_STATE(); RETURN();}void op_mfc1 (void){ T0 = WT0; DEBUG_FPU_STATE(); RETURN();}void op_mtc1 (void){ WT0 = T0; DEBUG_FPU_STATE(); RETURN();}/* Float support. Single precition routines have a "s" suffix, double precision a "d" suffix. */#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)FLOAT_OP(cvtd, s){ FDT2 = float32_to_float64(WT0, &env->fp_status); DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(cvtd, w){ FDT2 = int32_to_float64(WT0, &env->fp_status); DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(cvts, d){ FST2 = float64_to_float32(FDT0, &env->fp_status); DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(cvts, w){ FST2 = int32_to_float32(WT0, &env->fp_status); DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(cvtw, s){ WT2 = float32_to_int32(FST0, &env->fp_status); DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(cvtw, d){ WT2 = float64_to_int32(FDT0, &env->fp_status); DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(roundw, d){ set_float_rounding_mode(float_round_nearest_even, &env->fp_status); WT2 = float64_round_to_int(FDT0, &env->fp_status); RESTORE_ROUNDING_MODE; DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(roundw, s){ set_float_rounding_mode(float_round_nearest_even, &env->fp_status); WT2 = float32_round_to_int(FST0, &env->fp_status); RESTORE_ROUNDING_MODE; DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(truncw, d){ WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status); DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(truncw, s){ WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status); DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(ceilw, d){ set_float_rounding_mode(float_round_up, &env->fp_status); WT2 = float64_round_to_int(FDT0, &env->fp_status); RESTORE_ROUNDING_MODE; DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(ceilw, s){ set_float_rounding_mode(float_round_up, &env->fp_status); WT2 = float32_round_to_int(FST0, &env->fp_status); RESTORE_ROUNDING_MODE; DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(floorw, d){ set_float_rounding_mode(float_round_down, &env->fp_status); WT2 = float64_round_to_int(FDT0, &env->fp_status); RESTORE_ROUNDING_MODE; DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(floorw, s){ set_float_rounding_mode(float_round_down, &env->fp_status); WT2 = float32_round_to_int(FST0, &env->fp_status); RESTORE_ROUNDING_MODE; DEBUG_FPU_STATE(); RETURN();}/* binary operations */#define FLOAT_BINOP(name) \FLOAT_OP(name, d) \{ \ FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \ DEBUG_FPU_STATE(); \} \FLOAT_OP(name, s) \{ \ FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ DEBUG_FPU_STATE(); \}FLOAT_BINOP(add)FLOAT_BINOP(sub)FLOAT_BINOP(mul)FLOAT_BINOP(div)#undef FLOAT_BINOP/* unary operations, modifying fp status */#define FLOAT_UNOP(name) \FLOAT_OP(name, d) \{ \ FDT2 = float64_ ## name(FDT0, &env->fp_status); \ DEBUG_FPU_STATE(); \} \FLOAT_OP(name, s) \{ \ FST2 = float32_ ## name(FST0, &env->fp_status); \ DEBUG_FPU_STATE(); \}FLOAT_UNOP(sqrt)#undef FLOAT_UNOP/* unary operations, not modifying fp status */#define FLOAT_UNOP(name) \FLOAT_OP(name, d) \{ \ FDT2 = float64_ ## name(FDT0); \ DEBUG_FPU_STATE(); \} \FLOAT_OP(name, s) \{ \ FST2 = float32_ ## name(FST0); \ DEBUG_FPU_STATE(); \}FLOAT_UNOP(abs)FLOAT_UNOP(chs)#undef FLOAT_UNOPFLOAT_OP(mov, d){ FDT2 = FDT0; DEBUG_FPU_STATE(); RETURN();}FLOAT_OP(mov, s){ FST2 = FST0; DEBUG_FPU_STATE(); RETURN();}#ifdef CONFIG_SOFTFLOAT#define clear_invalid() do { \ int flags = get_float_exception_flags(&env->fp_status); \ flags &= ~float_flag_invalid; \ set_float_exception_flags(flags, &env->fp_status); \} while(0)#else#define clear_invalid() do { } while(0)#endifextern void dump_fpu_s(CPUState *env);#define FOP_COND(fmt, op, sig, cond) \void op_cmp_ ## fmt ## _ ## op (void) \{ \ if (cond) \ SET_FP_COND(env->fcr31); \ else \ CLEAR_FP_COND(env->fcr31); \ if (!sig) \ clear_invalid(); \ /*CALL_FROM_TB1(dump_fpu_s, env);*/ \ DEBUG_FPU_STATE(); \ RETURN(); \}int float64_is_unordered(float64 a, float64 b STATUS_PARAM){ if (float64_is_nan(a) || float64_is_nan(b)) { float_raise(float_flag_invalid, status); return 1; } else { return 0; }}FOP_COND(d, f, 0, 0) FOP_COND(d, un, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status))FOP_COND(d, eq, 0, float64_eq(FDT0, FDT1, &env->fp_status))FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))FOP_COND(d, olt, 0, float64_lt(FDT0, FDT1, &env->fp_status))FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))FOP_COND(d, ole, 0, float64_le(FDT0, FDT1, &env->fp_status))FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))/* NOTE: the comma operator will make "cond" to eval to false, * but float*_is_unordered() is still called */FOP_COND(d, sf, 1, (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0))FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status))FOP_COND(d, seq, 1, float64_eq(FDT0, FDT1, &env->fp_status))FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))FOP_COND(d, lt, 1, float64_lt(FDT0, FDT1, &env->fp_status))FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))FOP_COND(d, le, 1, float64_le(FDT0, FDT1, &env->fp_status))FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))flag float32_is_unordered(float32 a, float32 b STATUS_PARAM){ extern flag float32_is_nan( float32 a ); if (float32_is_nan(a) || float32_is_nan(b)) { float_raise(float_flag_invalid, status); return 1; } else { return 0; }}/* NOTE: the comma operator will make "cond" to eval to false, * but float*_is_unordered() is still called */FOP_COND(s, f, 0, 0) FOP_COND(s, un, 0, float32_is_unordered(FST1, FST0, &env->fp_status))FOP_COND(s, eq, 0, float32_eq(FST0, FST1, &env->fp_status))FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))FOP_COND(s, olt, 0, float32_lt(FST0, FST1, &env->fp_status))FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))FOP_COND(s, ole, 0, float32_le(FST0, FST1, &env->fp_status))FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))/* NOTE: the comma operator will make "cond" to eval to false, * but float*_is_unordered() is still called */FOP_COND(s, sf, 1, (float32_is_unordered(FST0, FST1, &env->fp_status), 0))FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status))FOP_COND(s, seq, 1, float32_eq(FST0, FST1, &env->fp_status))FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))FOP_COND(s, lt, 1, float32_lt(FST0, FST1, &env->fp_status))FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))FOP_COND(s, le, 1, float32_le(FST0, FST1, &env->fp_status))FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))void op_bc1f (void){ T0 = ! IS_FP_COND_SET(env->fcr31); DEBUG_FPU_STATE(); RETURN();}void op_bc1t (void){ T0 = IS_FP_COND_SET(env->fcr31); DEBUG_FPU_STATE(); RETURN();}#endif /* MIPS_USES_FPU */#if defined(MIPS_USES_R4K_TLB)void op_tlbwi (void){ CALL_FROM_TB0(do_tlbwi); RETURN();}void op_tlbwr (void){ CALL_FROM_TB0(do_tlbwr); RETURN();}void op_tlbp (void){ CALL_FROM_TB0(do_tlbp); RETURN();}void op_tlbr (void){ CALL_FROM_TB0(do_tlbr); RETURN();}#endif/* Specials */void op_pmon (void){ CALL_FROM_TB1(do_pmon, PARAM1); RETURN();}void op_di (void){ T0 = env->CP0_Status; env->CP0_Status = T0 & ~(1 << CP0St_IE); CALL_FROM_TB1(cpu_mips_update_irq, env); RETURN();}void op_ei (void){ T0 = env->CP0_Status; env->CP0_Status = T0 | (1 << CP0St_IE); CALL_FROM_TB1(cpu_mips_update_irq, env); RETURN();}void op_trap (void){ if (T0) { CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP); } RETURN();}void op_debug (void){ CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG); RETURN();}void op_set_lladdr (void){ env->CP0_LLAddr = T2; RETURN();}void debug_eret (void);void op_eret (void){ CALL_FROM_TB0(debug_eret); if (env->hflags & MIPS_HFLAG_ERL) { env->PC = env->CP0_ErrorEPC; env->hflags &= ~MIPS_HFLAG_ERL; env->CP0_Status &= ~(1 << CP0St_ERL); } else { env->PC = env->CP0_EPC; env->hflags &= ~MIPS_HFLAG_EXL; env->CP0_Status &= ~(1 << CP0St_EXL); } env->CP0_LLAddr = 1; RETURN();}void op_deret (void){ CALL_FROM_TB0(debug_eret); env->PC = env->CP0_DEPC; RETURN();}void op_rdhwr_cpunum(void){ if (env->CP0_HWREna & (1 << 0)) T0 = env->CP0_EBase & 0x2ff; else CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI); RETURN();}void op_rdhwr_synci_step(void){ if (env->CP0_HWREna & (1 << 1)) T0 = env->SYNCI_Step; else CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI); RETURN();}void op_rdhwr_cc(void){ if (env->CP0_HWREna & (1 << 2)) T0 = env->CP0_Count; else CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI); RETURN();}void op_rdhwr_ccres(void){ if (env->CP0_HWREna & (1 << 3)) T0 = env->CCRes; else CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI); RETURN();}void op_save_state (void){ env->hflags = PARAM1; RETURN();}void op_save_pc (void){ env->PC = PARAM1; RETURN();}void op_raise_exception (void){ CALL_FROM_TB1(do_raise_exception, PARAM1); RETURN();}void op_raise_exception_err (void){ CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2); RETURN();}void op_exit_tb (void){ EXIT_TB(); RETURN();}void op_wait (void){ env->halted = 1; CALL_FROM_TB1(do_raise_exception, EXCP_HLT); RETURN();}/* Bitfield operations. */void op_ext(void){ unsigned int pos = PARAM1; unsigned int size = PARAM2; T0 = ((uint32_t)T1 >> pos) & ((1 << size) - 1); RETURN();}void op_ins(void){ unsigned int pos = PARAM1; unsigned int size = PARAM2; target_ulong mask = ((1 << size) - 1) << pos; T0 = (T2 & ~mask) | (((uint32_t)T1 << pos) & mask); RETURN();}void op_wsbh(void){ T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF); RETURN();}#ifdef MIPS_HAS_MIPS64void op_dext(void){ unsigned int pos = PARAM1; unsigned int size = PARAM2; T0 = (T1 >> pos) & ((1 << size) - 1); RETURN();}void op_dins(void){ unsigned int pos = PARAM1; unsigned int size = PARAM2; target_ulong mask = ((1 << size) - 1) << pos; T0 = (T2 & ~mask) | ((T1 << pos) & mask); RETURN();}void op_dsbh(void){ T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL); RETURN();}void op_dshd(void){ T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL); RETURN();}#endifvoid op_seb(void){ T0 = ((T1 & 0xFF) ^ 0x80) - 0x80; RETURN();}void op_seh(void){ T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000; RETURN();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -