diff options
Diffstat (limited to 'target-mips/op_helper.c')
-rw-r--r-- | target-mips/op_helper.c | 147 |
1 files changed, 81 insertions, 66 deletions
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index f4313280e..032302161 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -20,7 +20,13 @@ #include <stdlib.h> #include "exec.h" -#define GETPC() (__builtin_return_address(0)) +#include "host-utils.h" + +#ifdef __s390__ +# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL)) +#else +# define GETPC() (__builtin_return_address(0)) +#endif /*****************************************************************************/ /* Exceptions processing helpers */ @@ -62,19 +68,7 @@ void do_raise_exception_direct (uint32_t exception) do_raise_exception_direct_err (exception, 0); } -#define MEMSUFFIX _raw -#include "op_helper_mem.c" -#undef MEMSUFFIX -#if !defined(CONFIG_USER_ONLY) -#define MEMSUFFIX _user -#include "op_helper_mem.c" -#undef MEMSUFFIX -#define MEMSUFFIX _kernel -#include "op_helper_mem.c" -#undef MEMSUFFIX -#endif - -#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64) +#if defined(TARGET_MIPS64) #if TARGET_LONG_BITS > HOST_LONG_BITS /* Those might call libgcc functions. */ void do_dsll (void) @@ -112,8 +106,8 @@ void do_drotr (void) target_ulong tmp; if (T1) { - tmp = T0 << (0x40 - T1); - T0 = (T0 >> T1) | tmp; + tmp = T0 << (0x40 - T1); + T0 = (T0 >> T1) | tmp; } } @@ -121,10 +115,8 @@ void do_drotr32 (void) { target_ulong tmp; - if (T1) { - tmp = T0 << (0x40 - (32 + T1)); - T0 = (T0 >> (32 + T1)) | tmp; - } + tmp = T0 << (0x40 - (32 + T1)); + T0 = (T0 >> (32 + T1)) | tmp; } void do_dsllv (void) @@ -148,22 +140,33 @@ void do_drotrv (void) T0 &= 0x3F; if (T0) { - tmp = T1 << (0x40 - T0); - T0 = (T1 >> T0) | tmp; + tmp = T1 << (0x40 - T0); + T0 = (T1 >> T0) | tmp; } else - T0 = T1; + T0 = T1; +} + +void do_dclo (void) +{ + T0 = clo64(T0); } + +void do_dclz (void) +{ + T0 = clz64(T0); +} + #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */ -#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */ +#endif /* TARGET_MIPS64 */ /* 64 bits arithmetic for 32 bits hosts */ #if TARGET_LONG_BITS > HOST_LONG_BITS -static inline uint64_t get_HILO (void) +static always_inline uint64_t get_HILO (void) { return (env->HI[0][env->current_tc] << 32) | (uint32_t)env->LO[0][env->current_tc]; } -static inline void set_HILO (uint64_t HILO) +static always_inline void set_HILO (uint64_t HILO) { env->LO[0][env->current_tc] = (int32_t)HILO; env->HI[0][env->current_tc] = (int32_t)(HILO >> 32); @@ -223,7 +226,7 @@ void do_div (void) } #endif -#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64) +#if defined(TARGET_MIPS64) void do_ddiv (void) { if (T1 != 0) { @@ -242,7 +245,7 @@ void do_ddivu (void) } } #endif -#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */ +#endif /* TARGET_MIPS64 */ #if defined(CONFIG_USER_ONLY) void do_mfc0_random (void) @@ -314,8 +317,12 @@ void do_mtc0_status_debug(uint32_t old, uint32_t val) old, old & env->CP0_Cause & CP0Ca_IP_mask, val, val & env->CP0_Cause & CP0Ca_IP_mask, env->CP0_Cause); - (env->hflags & MIPS_HFLAG_UM) ? fputs(", UM\n", logfile) - : fputs("\n", logfile); + switch (env->hflags & MIPS_HFLAG_KSU) { + case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break; + case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break; + case MIPS_HFLAG_KM: fputs("\n", logfile); break; + default: cpu_abort(env, "Invalid MMU mode!\n"); break; + } } void do_mtc0_status_irqraise_debug(void) @@ -383,7 +390,7 @@ static void r4k_fill_tlb (int idx) /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ tlb = &env->tlb->mmu.r4k.tlb[idx]; tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); -#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64) +#if defined(TARGET_MIPS64) tlb->VPN &= env->SEGMask; #endif tlb->ASID = env->CP0_EntryHi & 0xFF; @@ -517,10 +524,12 @@ void debug_post_eret (void) fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); if (env->hflags & MIPS_HFLAG_DM) fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC); - if (env->hflags & MIPS_HFLAG_UM) - fputs(", UM\n", logfile); - else - fputs("\n", logfile); + switch (env->hflags & MIPS_HFLAG_KSU) { + case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break; + case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break; + case MIPS_HFLAG_KM: fputs("\n", logfile); break; + default: cpu_abort(env, "Invalid MMU mode!\n"); break; + } } void do_pmon (int function) @@ -575,7 +584,7 @@ static void do_unaligned_access (target_ulong addr, int is_write, int is_user, v do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL); } -void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) +void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) { TranslationBlock *tb; CPUState *saved_env; @@ -586,7 +595,7 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_mips_handle_mmu_fault(env, addr, is_write, is_user, 1); + ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); if (ret) { if (retaddr) { /* now we have a real cpu fault */ @@ -603,16 +612,22 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) env = saved_env; } +void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, + int unused) +{ + if (is_exec) + do_raise_exception(EXCP_IBE); + else + do_raise_exception(EXCP_DBE); +} #endif /* Complex FPU operations which may need stack space. */ -#define FLOAT_SIGN32 (1 << 31) -#define FLOAT_SIGN64 (1ULL << 63) -#define FLOAT_ONE32 (0x3f8 << 20) -#define FLOAT_ONE64 (0x3ffULL << 52) -#define FLOAT_TWO32 (1 << 30) -#define FLOAT_TWO64 (1ULL << 62) +#define FLOAT_ONE32 make_float32(0x3f8 << 20) +#define FLOAT_ONE64 make_float64(0x3ffULL << 52) +#define FLOAT_TWO32 make_float32(1 << 30) +#define FLOAT_TWO64 make_float64(1ULL << 62) #define FLOAT_QNAN32 0x7fbfffff #define FLOAT_QNAN64 0x7ff7ffffffffffffULL #define FLOAT_SNAN32 0x7fffffff @@ -685,7 +700,7 @@ void do_ctc1 (int reg) do_raise_exception(EXCP_FPE); } -inline char ieee_ex_to_mips(char xcpt) +static always_inline char ieee_ex_to_mips(char xcpt) { return (xcpt & float_flag_inexact) >> 5 | (xcpt & float_flag_underflow) >> 3 | @@ -694,7 +709,7 @@ inline char ieee_ex_to_mips(char xcpt) (xcpt & float_flag_invalid) << 4; } -inline char mips_ex_to_ieee(char xcpt) +static always_inline char mips_ex_to_ieee(char xcpt) { return (xcpt & FP_INEXACT) << 5 | (xcpt & FP_UNDERFLOW) << 3 | @@ -703,7 +718,7 @@ inline char mips_ex_to_ieee(char xcpt) (xcpt & FP_INVALID) >> 4; } -inline void update_fcr31(void) +static always_inline void update_fcr31(void) { int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fpu->fp_status)); @@ -1035,7 +1050,7 @@ FLOAT_OP(name, d) \ FDT2 = float64_ ## name (FDT0, FDT1, &env->fpu->fp_status); \ update_fcr31(); \ if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) \ - FDT2 = FLOAT_QNAN64; \ + DT2 = FLOAT_QNAN64; \ } \ FLOAT_OP(name, s) \ { \ @@ -1043,7 +1058,7 @@ FLOAT_OP(name, s) \ FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status); \ update_fcr31(); \ if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) \ - FST2 = FLOAT_QNAN32; \ + WT2 = FLOAT_QNAN32; \ } \ FLOAT_OP(name, ps) \ { \ @@ -1052,8 +1067,8 @@ FLOAT_OP(name, ps) \ FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fpu->fp_status); \ update_fcr31(); \ if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) { \ - FST2 = FLOAT_QNAN32; \ - FSTH2 = FLOAT_QNAN32; \ + WT2 = FLOAT_QNAN32; \ + WTH2 = FLOAT_QNAN32; \ } \ } FLOAT_BINOP(add) @@ -1067,14 +1082,14 @@ FLOAT_OP(recip2, d) { set_float_exception_flags(0, &env->fpu->fp_status); FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status); - FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status) ^ FLOAT_SIGN64; + FDT2 = float64_chs(float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status)); update_fcr31(); } FLOAT_OP(recip2, s) { set_float_exception_flags(0, &env->fpu->fp_status); FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); - FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status) ^ FLOAT_SIGN32; + FST2 = float32_chs(float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status)); update_fcr31(); } FLOAT_OP(recip2, ps) @@ -1082,8 +1097,8 @@ FLOAT_OP(recip2, ps) set_float_exception_flags(0, &env->fpu->fp_status); FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status); - FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status) ^ FLOAT_SIGN32; - FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status) ^ FLOAT_SIGN32; + FST2 = float32_chs(float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status)); + FSTH2 = float32_chs(float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status)); update_fcr31(); } @@ -1092,7 +1107,7 @@ FLOAT_OP(rsqrt2, d) set_float_exception_flags(0, &env->fpu->fp_status); FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status); FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status); - FDT2 = float64_div(FDT2, FLOAT_TWO64, &env->fpu->fp_status) ^ FLOAT_SIGN64; + FDT2 = float64_chs(float64_div(FDT2, FLOAT_TWO64, &env->fpu->fp_status)); update_fcr31(); } FLOAT_OP(rsqrt2, s) @@ -1100,7 +1115,7 @@ FLOAT_OP(rsqrt2, s) set_float_exception_flags(0, &env->fpu->fp_status); FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status); - FST2 = float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status) ^ FLOAT_SIGN32; + FST2 = float32_chs(float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status)); update_fcr31(); } FLOAT_OP(rsqrt2, ps) @@ -1110,8 +1125,8 @@ FLOAT_OP(rsqrt2, ps) FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status); FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status); FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status); - FST2 = float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status) ^ FLOAT_SIGN32; - FSTH2 = float32_div(FSTH2, FLOAT_TWO32, &env->fpu->fp_status) ^ FLOAT_SIGN32; + FST2 = float32_chs(float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status)); + FSTH2 = float32_chs(float32_div(FSTH2, FLOAT_TWO32, &env->fpu->fp_status)); update_fcr31(); } @@ -1145,8 +1160,8 @@ void do_cmp_d_ ## op (long cc) \ void do_cmpabs_d_ ## op (long cc) \ { \ int c; \ - FDT0 &= ~FLOAT_SIGN64; \ - FDT1 &= ~FLOAT_SIGN64; \ + FDT0 = float64_chs(FDT0); \ + FDT1 = float64_chs(FDT1); \ c = cond; \ update_fcr31(); \ if (c) \ @@ -1203,8 +1218,8 @@ void do_cmp_s_ ## op (long cc) \ void do_cmpabs_s_ ## op (long cc) \ { \ int c; \ - FST0 &= ~FLOAT_SIGN32; \ - FST1 &= ~FLOAT_SIGN32; \ + FST0 = float32_abs(FST0); \ + FST1 = float32_abs(FST1); \ c = cond; \ update_fcr31(); \ if (c) \ @@ -1266,10 +1281,10 @@ void do_cmp_ps_ ## op (long cc) \ void do_cmpabs_ps_ ## op (long cc) \ { \ int cl, ch; \ - FST0 &= ~FLOAT_SIGN32; \ - FSTH0 &= ~FLOAT_SIGN32; \ - FST1 &= ~FLOAT_SIGN32; \ - FSTH1 &= ~FLOAT_SIGN32; \ + FST0 = float32_abs(FST0); \ + FSTH0 = float32_abs(FSTH0); \ + FST1 = float32_abs(FST1); \ + FSTH1 = float32_abs(FSTH1); \ cl = condl; \ ch = condh; \ update_fcr31(); \ |