aboutsummaryrefslogtreecommitdiff
path: root/target-mips/op_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-mips/op_helper.c')
-rw-r--r--target-mips/op_helper.c147
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(); \