aboutsummaryrefslogtreecommitdiff
path: root/target-mips
diff options
context:
space:
mode:
authorFathi Boudra <fathi.boudra@linaro.org>2013-08-05 10:19:49 +0300
committerFathi Boudra <fathi.boudra@linaro.org>2013-08-05 10:19:49 +0300
commit86342dcc9b73eac8310b9dc5fd1356bbfa5b9c8e (patch)
treec9987b94bab825a920990236234da4747d565f37 /target-mips
parent050a840ead5e51a1a9f3bffe89cc89077b2f35ed (diff)
Imported Upstream version 1.5.0-2013.06+git74+20130802+ef1b0aeupstream
Diffstat (limited to 'target-mips')
-rw-r--r--target-mips/cpu-qom.h5
-rw-r--r--target-mips/cpu.c23
-rw-r--r--target-mips/cpu.h9
-rw-r--r--target-mips/dsp_helper.c201
-rw-r--r--target-mips/helper.c5
-rw-r--r--target-mips/helper.h2
-rw-r--r--target-mips/op_helper.c35
-rw-r--r--target-mips/translate.c221
8 files changed, 244 insertions, 257 deletions
diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h
index 2a4b812..32e3cad 100644
--- a/target-mips/cpu-qom.h
+++ b/target-mips/cpu-qom.h
@@ -37,6 +37,7 @@
/**
* MIPSCPUClass:
+ * @parent_realize: The parent class' realize handler.
* @parent_reset: The parent class' reset handler.
*
* A MIPS CPU model.
@@ -46,6 +47,7 @@ typedef struct MIPSCPUClass {
CPUClass parent_class;
/*< public >*/
+ DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu);
} MIPSCPUClass;
@@ -70,5 +72,8 @@ static inline MIPSCPU *mips_env_get_cpu(CPUMIPSState *env)
#define ENV_GET_CPU(e) CPU(mips_env_get_cpu(e))
+#define ENV_OFFSET offsetof(MIPSCPU, env)
+
+void mips_cpu_do_interrupt(CPUState *cpu);
#endif
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index 10ff46d..5315f7b 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -42,21 +42,44 @@ static void mips_cpu_reset(CPUState *s)
cpu_state_reset(env);
}
+static void mips_cpu_realizefn(DeviceState *dev, Error **errp)
+{
+ MIPSCPU *cpu = MIPS_CPU(dev);
+ MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev);
+
+ cpu_reset(CPU(cpu));
+ qemu_init_vcpu(&cpu->env);
+
+ mcc->parent_realize(dev, errp);
+}
+
static void mips_cpu_initfn(Object *obj)
{
+ CPUState *cs = CPU(obj);
MIPSCPU *cpu = MIPS_CPU(obj);
CPUMIPSState *env = &cpu->env;
+ cs->env_ptr = env;
cpu_exec_init(env);
+
+ if (tcg_enabled()) {
+ mips_tcg_init();
+ }
}
static void mips_cpu_class_init(ObjectClass *c, void *data)
{
MIPSCPUClass *mcc = MIPS_CPU_CLASS(c);
CPUClass *cc = CPU_CLASS(c);
+ DeviceClass *dc = DEVICE_CLASS(c);
+
+ mcc->parent_realize = dc->realize;
+ dc->realize = mips_cpu_realizefn;
mcc->parent_reset = cc->reset;
cc->reset = mips_cpu_reset;
+
+ cc->do_interrupt = mips_cpu_do_interrupt;
}
static const TypeInfo mips_cpu_type_info = {
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 5963d62..cedf03d 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -504,6 +504,9 @@ void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
#define cpu_signal_handler cpu_mips_signal_handler
#define cpu_list mips_cpu_list
+extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env);
+extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
+
#define CPU_SAVE_VERSION 3
/* MMU modes definitions. We carefully match the indices with our
@@ -629,6 +632,7 @@ enum {
#define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0
int cpu_mips_exec(CPUMIPSState *s);
+void mips_tcg_init(void);
MIPSCPU *cpu_mips_init(const char *cpu_model);
int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
@@ -659,7 +663,6 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level);
int cpu_mips_handle_mmu_fault (CPUMIPSState *env, target_ulong address, int rw,
int mmu_idx);
#define cpu_handle_mmu_fault cpu_mips_handle_mmu_fault
-void do_interrupt (CPUMIPSState *env);
#if !defined(CONFIG_USER_ONLY)
void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra);
hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address,
@@ -718,7 +721,7 @@ static inline bool cpu_has_work(CPUState *cpu)
/* It is implementation dependent if non-enabled interrupts
wake-up the CPU, however most of the implementations only
check for interrupts that can be taken. */
- if ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+ if ((cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
cpu_mips_hw_interrupts_pending(env)) {
has_work = true;
}
@@ -727,7 +730,7 @@ static inline bool cpu_has_work(CPUState *cpu)
if (env->CP0_Config3 & (1 << CP0C3_MT)) {
/* The QEMU model will issue an _WAKE request whenever the CPUs
should be woken up. */
- if (env->interrupt_request & CPU_INTERRUPT_WAKE) {
+ if (cpu->interrupt_request & CPU_INTERRUPT_WAKE) {
has_work = true;
}
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 96cb044..918a898 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -19,6 +19,7 @@
#include "cpu.h"
#include "helper.h"
+#include "qemu/bitops.h"
/* As the byte ordering doesn't matter, i.e. all columns are treated
identically, these unions can be used directly. */
@@ -44,7 +45,8 @@ typedef union {
/*** MIPS DSP internal functions begin ***/
#define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x)
-#define MIPSDSP_OVERFLOW(a, b, c, d) (!(!((a ^ b ^ -1) & (a ^ c) & d)))
+#define MIPSDSP_OVERFLOW_ADD(a, b, c, d) (~(a ^ b) & (a ^ c) & d)
+#define MIPSDSP_OVERFLOW_SUB(a, b, c, d) ((a ^ b) & (a ^ c) & d)
static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
CPUMIPSState *env)
@@ -52,9 +54,10 @@ static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
env->active_tc.DSPControl |= (target_ulong)flag << position;
}
-static inline void set_DSPControl_carryflag(uint32_t flag, CPUMIPSState *env)
+static inline void set_DSPControl_carryflag(bool flag, CPUMIPSState *env)
{
- env->active_tc.DSPControl |= (target_ulong)flag << 13;
+ env->active_tc.DSPControl &= ~(1 << 13);
+ env->active_tc.DSPControl |= flag << 13;
}
static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
@@ -89,10 +92,10 @@ static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env)
dspc = env->active_tc.DSPControl;
#ifndef TARGET_MIPS64
dspc = dspc & 0xFFFFFFC0;
- dspc |= pos;
+ dspc |= (pos & 0x3F);
#else
dspc = dspc & 0xFFFFFF80;
- dspc |= pos;
+ dspc |= (pos & 0x7F);
#endif
env->active_tc.DSPControl = dspc;
}
@@ -142,7 +145,7 @@ static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env)
tempI = a + b;
- if (MIPSDSP_OVERFLOW(a, b, tempI, 0x8000)) {
+ if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x8000)) {
set_DSPControl_overflow_flag(1, 20, env);
}
@@ -156,7 +159,7 @@ static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b,
tempS = a + b;
- if (MIPSDSP_OVERFLOW(a, b, tempS, 0x8000)) {
+ if (MIPSDSP_OVERFLOW_ADD(a, b, tempS, 0x8000)) {
if (a > 0) {
tempS = 0x7FFF;
} else {
@@ -175,7 +178,7 @@ static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b,
tempI = a + b;
- if (MIPSDSP_OVERFLOW(a, b, tempI, 0x80000000)) {
+ if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x80000000)) {
if (a > 0) {
tempI = 0x7FFFFFFF;
} else {
@@ -268,18 +271,6 @@ static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a,
temp31 = (temp_sum >> 31) & 0x01;
result = temp_sum & 0xFFFFFFFF;
- /* FIXME
- This sat function may wrong, because user manual wrote:
- temp127..0 ← temp + ( (signA) || a31..0
- if ( temp32 ≠ temp31 ) then
- if ( temp32 = 0 ) then
- temp31..0 ← 0x80000000
- else
- temp31..0 ← 0x7FFFFFFF
- endif
- DSPControlouflag:16+acc ← 1
- endif
- */
if (temp32 != temp31) {
if (temp32 == 0) {
result = 0x7FFFFFFF;
@@ -516,13 +507,8 @@ static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
acc = ((int64_t)env->active_tc.HI[ac] << 32) |
((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
- if (shift == 0) {
- p[0] = acc << 1;
- p[1] = (acc >> 63) & 0x01;
- } else {
- p[0] = acc >> (shift - 1);
- p[1] = 0;
- }
+ p[0] = (shift == 0) ? (acc << 1) : (acc >> (shift - 1));
+ p[1] = (acc >> 63) & 0x01;
}
/* 128 bits long. p[0] is LO, p[1] is HI */
@@ -582,7 +568,7 @@ static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b,
temp = 0x7FFFFFFF;
set_DSPControl_overflow_flag(1, 16 + ac, env);
} else {
- temp = ((uint32_t)a * (uint32_t)b) << 1;
+ temp = ((int16_t)a * (int16_t)b) << 1;
}
return temp;
@@ -652,7 +638,7 @@ static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b,
temp = 0x7FFF0000;
set_DSPControl_overflow_flag(1, 21, env);
} else {
- temp = ((uint32_t)a * (uint32_t)b);
+ temp = (int16_t)a * (int16_t)b;
temp = temp << 1;
}
@@ -698,49 +684,31 @@ static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env)
{
- uint8_t sign;
uint8_t discard;
- if (s == 0) {
- return a;
- } else {
- sign = (a >> 7) & 0x01;
- if (sign != 0) {
- discard = (((0x01 << (8 - s)) - 1) << s) |
- ((a >> (6 - (s - 1))) & ((0x01 << s) - 1));
- } else {
- discard = a >> (6 - (s - 1));
- }
+ if (s != 0) {
+ discard = a >> (8 - s);
if (discard != 0x00) {
set_DSPControl_overflow_flag(1, 22, env);
}
- return a << s;
}
+ return a << s;
}
static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
CPUMIPSState *env)
{
- uint8_t sign;
uint16_t discard;
- if (s == 0) {
- return a;
- } else {
- sign = (a >> 15) & 0x01;
- if (sign != 0) {
- discard = (((0x01 << (16 - s)) - 1) << s) |
- ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
- } else {
- discard = a >> (14 - (s - 1));
- }
+ if (s != 0) {
+ discard = (int16_t)a >> (15 - s);
if ((discard != 0x0000) && (discard != 0xFFFF)) {
set_DSPControl_overflow_flag(1, 22, env);
}
- return a << s;
}
+ return a << s;
}
@@ -858,7 +826,7 @@ static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env)
int16_t temp;
temp = a - b;
- if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
+ if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) {
set_DSPControl_overflow_flag(1, 20, env);
}
@@ -871,8 +839,8 @@ static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b,
int16_t temp;
temp = a - b;
- if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
- if (a > 0) {
+ if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) {
+ if (a >= 0) {
temp = 0x7FFF;
} else {
temp = 0x8000;
@@ -889,8 +857,8 @@ static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b,
int32_t temp;
temp = a - b;
- if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
- if (a > 0) {
+ if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) {
+ if (a >= 0) {
temp = 0x7FFFFFFF;
} else {
temp = 0x80000000;
@@ -1004,7 +972,7 @@ static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
int32_t temp;
temp = a - b;
- if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
+ if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) {
set_DSPControl_overflow_flag(1, 20, env);
}
@@ -1017,7 +985,7 @@ static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env)
temp = a + b;
- if (MIPSDSP_OVERFLOW(a, b, temp, 0x80000000)) {
+ if (MIPSDSP_OVERFLOW_ADD(a, b, temp, 0x80000000)) {
set_DSPControl_overflow_flag(1, 20, env);
}
@@ -1300,7 +1268,7 @@ SUBUH_QB(subuh_r, 1);
target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
{
uint64_t temp, tempRs, tempRt;
- int32_t flag;
+ bool flag;
tempRs = (uint64_t)rs & MIPSDSP_LLO;
tempRt = (uint64_t)rt & MIPSDSP_LLO;
@@ -2488,37 +2456,42 @@ DP_QH(dpsq_s_w_qh, 0, 1);
#endif
#define DP_L_W(name, is_add) \
-void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
- CPUMIPSState *env) \
-{ \
- int32_t temp63; \
- int64_t dotp, acc; \
- uint64_t temp; \
- \
- dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env); \
- acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
- ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
- if (!is_add) { \
- dotp = -dotp; \
- } \
- \
- temp = acc + dotp; \
- if (MIPSDSP_OVERFLOW((uint64_t)acc, (uint64_t)dotp, temp, \
- (0x01ull << 63))) { \
- temp63 = (temp >> 63) & 0x01; \
- if (temp63 == 1) { \
- temp = (0x01ull << 63) - 1; \
- } else { \
- temp = 0x01ull << 63; \
- } \
- \
- set_DSPControl_overflow_flag(1, 16 + ac, env); \
- } \
- \
- env->active_tc.HI[ac] = (target_long)(int32_t) \
- ((temp & MIPSDSP_LHI) >> 32); \
- env->active_tc.LO[ac] = (target_long)(int32_t) \
- (temp & MIPSDSP_LLO); \
+void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
+ CPUMIPSState *env) \
+{ \
+ int32_t temp63; \
+ int64_t dotp, acc; \
+ uint64_t temp; \
+ bool overflow; \
+ \
+ dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env); \
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
+ if (is_add) { \
+ temp = acc + dotp; \
+ overflow = MIPSDSP_OVERFLOW_ADD((uint64_t)acc, (uint64_t)dotp, \
+ temp, (0x01ull << 63)); \
+ } else { \
+ temp = acc - dotp; \
+ overflow = MIPSDSP_OVERFLOW_SUB((uint64_t)acc, (uint64_t)dotp, \
+ temp, (0x01ull << 63)); \
+ } \
+ \
+ if (overflow) { \
+ temp63 = (temp >> 63) & 0x01; \
+ if (temp63 == 1) { \
+ temp = (0x01ull << 63) - 1; \
+ } else { \
+ temp = 0x01ull << 63; \
+ } \
+ \
+ set_DSPControl_overflow_flag(1, 16 + ac, env); \
+ } \
+ \
+ env->active_tc.HI[ac] = (target_long)(int32_t) \
+ ((temp & MIPSDSP_LHI) >> 32); \
+ env->active_tc.LO[ac] = (target_long)(int32_t) \
+ (temp & MIPSDSP_LLO); \
}
DP_L_W(dpaq_sa_l_w, 1);
@@ -2689,7 +2662,7 @@ MAQ_SA_W(maq_sa_w_phr, 0);
target_ulong helper_##name(target_ulong rs, target_ulong rt, \
CPUMIPSState *env) \
{ \
- uint32_t rs_t, rt_t; \
+ int32_t rs_t, rt_t; \
int32_t tempI; \
int64_t tempL; \
\
@@ -2950,7 +2923,7 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \
return rt; \
} \
\
- filter = ((int32_t)0x01 << size) - 1; \
+ filter = ((int64_t)0x01 << size) - 1; \
filter = filter << pos; \
temprs = (rs << pos) & filter; \
temprt = rt & ~filter; \
@@ -2959,7 +2932,7 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \
return (target_long)(ret_type)temp; \
}
-BIT_INSV(insv, 0x1F, 0x1F, int32_t);
+BIT_INSV(insv, 0x1F, 0x3F, int32_t);
#ifdef TARGET_MIPS64
BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
#endif
@@ -3155,8 +3128,8 @@ target_ulong helper_extr_w(target_ulong ac, target_ulong shift,
tempDL[1] += 1;
}
- if ((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) &&
- (!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI))) {
+ if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+ ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
set_DSPControl_overflow_flag(1, 23, env);
}
@@ -3181,8 +3154,8 @@ target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
tempDL[1] += 1;
}
- if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
- (tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+ if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+ ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
set_DSPControl_overflow_flag(1, 23, env);
}
@@ -3208,9 +3181,9 @@ target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
}
tempI = tempDL[0] >> 1;
- if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
- (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
- temp64 = tempDL[1];
+ if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+ ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+ temp64 = tempDL[1] & 0x01;
if (temp64 == 0) {
tempI = 0x7FFFFFFF;
} else {
@@ -3444,8 +3417,7 @@ target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState *env)
if (sub >= -1) {
acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
- temp = (acc >> (start_pos - size)) &
- (((uint32_t)0x01 << (size + 1)) - 1);
+ temp = (acc >> (start_pos - size)) & (~0U >> (31 - size));
set_DSPControl_efi(0, env);
} else {
set_DSPControl_efi(1, env);
@@ -3469,10 +3441,9 @@ target_ulong helper_extpdp(target_ulong ac, target_ulong size,
if (sub >= -1) {
acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
- temp = (acc >> (start_pos - size)) &
- (((uint32_t)0x01 << (size + 1)) - 1);
+ temp = extract64(acc, start_pos - size, size + 1);
- set_DSPControl_pos(start_pos - (size + 1), env);
+ set_DSPControl_pos(sub, env);
set_DSPControl_efi(0, env);
} else {
set_DSPControl_efi(1, env);
@@ -3637,7 +3608,7 @@ void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env)
}
#endif
-void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
+void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env)
{
uint8_t mask[6];
uint8_t i;
@@ -3703,7 +3674,12 @@ void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
env->active_tc.DSPControl = dsp;
}
-target_ulong helper_rddsp(target_ulong masknum, CPUMIPSState *env)
+void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
+{
+ return cpu_wrdsp(rs, mask_num, env);
+}
+
+uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env)
{
uint8_t mask[6];
uint32_t ruler, i;
@@ -3712,7 +3688,7 @@ target_ulong helper_rddsp(target_ulong masknum, CPUMIPSState *env)
ruler = 0x01;
for (i = 0; i < 6; i++) {
- mask[i] = (masknum & ruler) >> i ;
+ mask[i] = (mask_num & ruler) >> i ;
ruler = ruler << 1;
}
@@ -3754,6 +3730,11 @@ target_ulong helper_rddsp(target_ulong masknum, CPUMIPSState *env)
return temp;
}
+target_ulong helper_rddsp(target_ulong mask_num, CPUMIPSState *env)
+{
+ return cpu_rddsp(mask_num, env);
+}
+
#undef MIPSDSP_LHI
#undef MIPSDSP_LLO
diff --git a/target-mips/helper.c b/target-mips/helper.c
index e877b8d..3a54acf 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -396,10 +396,11 @@ static void set_hflags_for_handler (CPUMIPSState *env)
}
#endif
-void do_interrupt (CPUMIPSState *env)
+void mips_cpu_do_interrupt(CPUState *cs)
{
+ MIPSCPU *cpu = MIPS_CPU(cs);
+ CPUMIPSState *env = &cpu->env;
#if !defined(CONFIG_USER_ONLY)
- MIPSCPU *cpu = mips_env_get_cpu(env);
target_ulong offset;
int cause = -1;
const char *name;
diff --git a/target-mips/helper.h b/target-mips/helper.h
index cd48738..ed75e2c 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -24,8 +24,6 @@ DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, tl, tl)
#ifdef TARGET_MIPS64
DEF_HELPER_FLAGS_1(dclo, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_1(dclz, TCG_CALL_NO_RWG_SE, tl, tl)
-DEF_HELPER_3(dmult, void, env, tl, tl)
-DEF_HELPER_3(dmultu, void, env, tl, tl)
#endif
DEF_HELPER_3(muls, tl, env, tl, tl)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 526f84f..3fa0d00 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -267,18 +267,6 @@ target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1,
(uint64_t)(uint32_t)arg2);
}
-#ifdef TARGET_MIPS64
-void helper_dmult(CPUMIPSState *env, target_ulong arg1, target_ulong arg2)
-{
- muls64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
-}
-
-void helper_dmultu(CPUMIPSState *env, target_ulong arg1, target_ulong arg2)
-{
- mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
-}
-#endif
-
#ifndef CONFIG_USER_ONLY
static inline hwaddr do_translate_address(CPUMIPSState *env,
@@ -527,29 +515,30 @@ void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
/* SMP helpers. */
static bool mips_vpe_is_wfi(MIPSCPU *c)
{
+ CPUState *cpu = CPU(c);
CPUMIPSState *env = &c->env;
/* If the VPE is halted but otherwise active, it means it's waiting for
an interrupt. */
- return env->halted && mips_vpe_active(env);
+ return cpu->halted && mips_vpe_active(env);
}
-static inline void mips_vpe_wake(CPUMIPSState *c)
+static inline void mips_vpe_wake(MIPSCPU *c)
{
/* Dont set ->halted = 0 directly, let it be done via cpu_has_work
because there might be other conditions that state that c should
be sleeping. */
- cpu_interrupt(c, CPU_INTERRUPT_WAKE);
+ cpu_interrupt(CPU(c), CPU_INTERRUPT_WAKE);
}
static inline void mips_vpe_sleep(MIPSCPU *cpu)
{
- CPUMIPSState *c = &cpu->env;
+ CPUState *cs = CPU(cpu);
/* The VPE was shut off, really go to bed.
Reset any old _WAKE requests. */
- c->halted = 1;
- cpu_reset_interrupt(c, CPU_INTERRUPT_WAKE);
+ cs->halted = 1;
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
}
static inline void mips_tc_wake(MIPSCPU *cpu, int tc)
@@ -558,7 +547,7 @@ static inline void mips_tc_wake(MIPSCPU *cpu, int tc)
/* FIXME: TC reschedule. */
if (mips_vpe_active(c) && !mips_vpe_is_wfi(cpu)) {
- mips_vpe_wake(c);
+ mips_vpe_wake(cpu);
}
}
@@ -1736,7 +1725,7 @@ target_ulong helper_evpe(CPUMIPSState *env)
&& !mips_vpe_is_wfi(other_cpu)) {
/* Enable the VPE. */
other_cpu_env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
- mips_vpe_wake(other_cpu_env); /* And wake it up. */
+ mips_vpe_wake(other_cpu); /* And wake it up. */
}
other_cpu_env = other_cpu_env->next_cpu;
} while (other_cpu_env);
@@ -2111,8 +2100,10 @@ void helper_pmon(CPUMIPSState *env, int function)
void helper_wait(CPUMIPSState *env)
{
- env->halted = 1;
- cpu_reset_interrupt(env, CPU_INTERRUPT_WAKE);
+ CPUState *cs = CPU(mips_env_get_cpu(env));
+
+ cs->halted = 1;
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
helper_raise_exception(env, EXCP_HLT);
}
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 3b77b53..0a53203 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -2582,10 +2582,9 @@ static void gen_shift(DisasContext *ctx, uint32_t opc,
}
/* Arithmetic on HI/LO registers */
-static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
+static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
{
const char *opn = "hilo";
- unsigned int acc;
if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
/* Treat as NOP. */
@@ -2593,12 +2592,6 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
return;
}
- if (opc == OPC_MFHI || opc == OPC_MFLO) {
- acc = ((ctx->opcode) >> 21) & 0x03;
- } else {
- acc = ((ctx->opcode) >> 11) & 0x03;
- }
-
if (acc != 0) {
check_dsp(ctx);
}
@@ -2661,12 +2654,11 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
MIPS_DEBUG("%s %s", opn, regnames[reg]);
}
-static void gen_muldiv (DisasContext *ctx, uint32_t opc,
- int rs, int rt)
+static void gen_muldiv(DisasContext *ctx, uint32_t opc,
+ int acc, int rs, int rt)
{
const char *opn = "mul/div";
TCGv t0, t1;
- unsigned int acc;
t0 = tcg_temp_new();
t1 = tcg_temp_new();
@@ -2674,6 +2666,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
gen_load_gpr(t0, rs);
gen_load_gpr(t1, rt);
+ if (acc != 0) {
+ check_dsp(ctx);
+ }
+
switch (opc) {
case OPC_DIV:
{
@@ -2688,10 +2684,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
tcg_gen_or_tl(t2, t2, t3);
tcg_gen_movi_tl(t3, 0);
tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
- tcg_gen_div_tl(cpu_LO[0], t0, t1);
- tcg_gen_rem_tl(cpu_HI[0], t0, t1);
- tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
- tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
+ tcg_gen_div_tl(cpu_LO[acc], t0, t1);
+ tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
+ tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
+ tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
tcg_temp_free(t3);
tcg_temp_free(t2);
}
@@ -2704,10 +2700,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
tcg_gen_ext32u_tl(t0, t0);
tcg_gen_ext32u_tl(t1, t1);
tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
- tcg_gen_divu_tl(cpu_LO[0], t0, t1);
- tcg_gen_remu_tl(cpu_HI[0], t0, t1);
- tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
- tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
+ tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
+ tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
+ tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
+ tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
tcg_temp_free(t3);
tcg_temp_free(t2);
}
@@ -2715,47 +2711,29 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
break;
case OPC_MULT:
{
- TCGv_i64 t2 = tcg_temp_new_i64();
- TCGv_i64 t3 = tcg_temp_new_i64();
- acc = ((ctx->opcode) >> 11) & 0x03;
- if (acc != 0) {
- check_dsp(ctx);
- }
-
- tcg_gen_ext_tl_i64(t2, t0);
- tcg_gen_ext_tl_i64(t3, t1);
- tcg_gen_mul_i64(t2, t2, t3);
- tcg_temp_free_i64(t3);
- tcg_gen_trunc_i64_tl(t0, t2);
- tcg_gen_shri_i64(t2, t2, 32);
- tcg_gen_trunc_i64_tl(t1, t2);
- tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[acc], t0);
- tcg_gen_ext32s_tl(cpu_HI[acc], t1);
+ TCGv_i32 t2 = tcg_temp_new_i32();
+ TCGv_i32 t3 = tcg_temp_new_i32();
+ tcg_gen_trunc_tl_i32(t2, t0);
+ tcg_gen_trunc_tl_i32(t3, t1);
+ tcg_gen_muls2_i32(t2, t3, t2, t3);
+ tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
+ tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
+ tcg_temp_free_i32(t2);
+ tcg_temp_free_i32(t3);
}
opn = "mult";
break;
case OPC_MULTU:
{
- TCGv_i64 t2 = tcg_temp_new_i64();
- TCGv_i64 t3 = tcg_temp_new_i64();
- acc = ((ctx->opcode) >> 11) & 0x03;
- if (acc != 0) {
- check_dsp(ctx);
- }
-
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_extu_tl_i64(t2, t0);
- tcg_gen_extu_tl_i64(t3, t1);
- tcg_gen_mul_i64(t2, t2, t3);
- tcg_temp_free_i64(t3);
- tcg_gen_trunc_i64_tl(t0, t2);
- tcg_gen_shri_i64(t2, t2, 32);
- tcg_gen_trunc_i64_tl(t1, t2);
- tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[acc], t0);
- tcg_gen_ext32s_tl(cpu_HI[acc], t1);
+ TCGv_i32 t2 = tcg_temp_new_i32();
+ TCGv_i32 t3 = tcg_temp_new_i32();
+ tcg_gen_trunc_tl_i32(t2, t0);
+ tcg_gen_trunc_tl_i32(t3, t1);
+ tcg_gen_mulu2_i32(t2, t3, t2, t3);
+ tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
+ tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
+ tcg_temp_free_i32(t2);
+ tcg_temp_free_i32(t3);
}
opn = "multu";
break;
@@ -2771,8 +2749,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
tcg_gen_or_tl(t2, t2, t3);
tcg_gen_movi_tl(t3, 0);
tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
- tcg_gen_div_tl(cpu_LO[0], t0, t1);
- tcg_gen_rem_tl(cpu_HI[0], t0, t1);
+ tcg_gen_div_tl(cpu_LO[acc], t0, t1);
+ tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
tcg_temp_free(t3);
tcg_temp_free(t2);
}
@@ -2783,19 +2761,19 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
TCGv t2 = tcg_const_tl(0);
TCGv t3 = tcg_const_tl(1);
tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
- tcg_gen_divu_i64(cpu_LO[0], t0, t1);
- tcg_gen_remu_i64(cpu_HI[0], t0, t1);
+ tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
+ tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
tcg_temp_free(t3);
tcg_temp_free(t2);
}
opn = "ddivu";
break;
case OPC_DMULT:
- gen_helper_dmult(cpu_env, t0, t1);
+ tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
opn = "dmult";
break;
case OPC_DMULTU:
- gen_helper_dmultu(cpu_env, t0, t1);
+ tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
opn = "dmultu";
break;
#endif
@@ -2803,10 +2781,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
- acc = ((ctx->opcode) >> 11) & 0x03;
- if (acc != 0) {
- check_dsp(ctx);
- }
tcg_gen_ext_tl_i64(t2, t0);
tcg_gen_ext_tl_i64(t3, t1);
@@ -2827,10 +2801,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
- acc = ((ctx->opcode) >> 11) & 0x03;
- if (acc != 0) {
- check_dsp(ctx);
- }
tcg_gen_ext32u_tl(t0, t0);
tcg_gen_ext32u_tl(t1, t1);
@@ -2853,10 +2823,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
- acc = ((ctx->opcode) >> 11) & 0x03;
- if (acc != 0) {
- check_dsp(ctx);
- }
tcg_gen_ext_tl_i64(t2, t0);
tcg_gen_ext_tl_i64(t3, t1);
@@ -2877,10 +2843,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
- acc = ((ctx->opcode) >> 11) & 0x03;
- if (acc != 0) {
- check_dsp(ctx);
- }
tcg_gen_ext32u_tl(t0, t0);
tcg_gen_ext32u_tl(t1, t1);
@@ -10143,7 +10105,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
gen_logic(ctx, OPC_NOR, rx, ry, 0);
break;
case RR_MFHI:
- gen_HILO(ctx, OPC_MFHI, rx);
+ gen_HILO(ctx, OPC_MFHI, 0, rx);
break;
case RR_CNVT:
switch (cnvt_op) {
@@ -10175,7 +10137,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
}
break;
case RR_MFLO:
- gen_HILO(ctx, OPC_MFLO, rx);
+ gen_HILO(ctx, OPC_MFLO, 0, rx);
break;
#if defined (TARGET_MIPS64)
case RR_DSRA:
@@ -10196,33 +10158,33 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
break;
#endif
case RR_MULT:
- gen_muldiv(ctx, OPC_MULT, rx, ry);
+ gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
break;
case RR_MULTU:
- gen_muldiv(ctx, OPC_MULTU, rx, ry);
+ gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
break;
case RR_DIV:
- gen_muldiv(ctx, OPC_DIV, rx, ry);
+ gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
break;
case RR_DIVU:
- gen_muldiv(ctx, OPC_DIVU, rx, ry);
+ gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
break;
#if defined (TARGET_MIPS64)
case RR_DMULT:
check_mips_64(ctx);
- gen_muldiv(ctx, OPC_DMULT, rx, ry);
+ gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
break;
case RR_DMULTU:
check_mips_64(ctx);
- gen_muldiv(ctx, OPC_DMULTU, rx, ry);
+ gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
break;
case RR_DDIV:
check_mips_64(ctx);
- gen_muldiv(ctx, OPC_DDIV, rx, ry);
+ gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
break;
case RR_DDIVU:
check_mips_64(ctx);
- gen_muldiv(ctx, OPC_DDIVU, rx, ry);
+ gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
break;
#endif
default:
@@ -10931,11 +10893,11 @@ static void gen_pool16c_insn(DisasContext *ctx, int *is_branch)
break;
case MFHI16 + 0:
case MFHI16 + 1:
- gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
+ gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
break;
case MFLO16 + 0:
case MFLO16 + 1:
- gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
+ gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
break;
case BREAK16:
generate_exception(ctx, EXCP_BREAK);
@@ -11133,30 +11095,34 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
break;
case MULT:
mips32_op = OPC_MULT;
- goto do_muldiv;
+ goto do_mul;
case MULTU:
mips32_op = OPC_MULTU;
- goto do_muldiv;
+ goto do_mul;
case DIV:
mips32_op = OPC_DIV;
- goto do_muldiv;
+ goto do_div;
case DIVU:
mips32_op = OPC_DIVU;
- goto do_muldiv;
+ goto do_div;
+ do_div:
+ check_insn(ctx, ISA_MIPS32);
+ gen_muldiv(ctx, mips32_op, 0, rs, rt);
+ break;
case MADD:
mips32_op = OPC_MADD;
- goto do_muldiv;
+ goto do_mul;
case MADDU:
mips32_op = OPC_MADDU;
- goto do_muldiv;
+ goto do_mul;
case MSUB:
mips32_op = OPC_MSUB;
- goto do_muldiv;
+ goto do_mul;
case MSUBU:
mips32_op = OPC_MSUBU;
- do_muldiv:
+ do_mul:
check_insn(ctx, ISA_MIPS32);
- gen_muldiv(ctx, mips32_op, rs, rt);
+ gen_muldiv(ctx, mips32_op, (ctx->opcode >> 14) & 3, rs, rt);
break;
default:
goto pool32axf_invalid;
@@ -11293,18 +11259,18 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
}
break;
case 0x35:
- switch (minor) {
+ switch (minor & 3) {
case MFHI32:
- gen_HILO(ctx, OPC_MFHI, rs);
+ gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
break;
case MFLO32:
- gen_HILO(ctx, OPC_MFLO, rs);
+ gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
break;
case MTHI32:
- gen_HILO(ctx, OPC_MTHI, rs);
+ gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
break;
case MTLO32:
- gen_HILO(ctx, OPC_MTLO, rs);
+ gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
break;
default:
goto pool32axf_invalid;
@@ -13434,6 +13400,7 @@ static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
/* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
* the same mask and op1. */
case OPC_MULT_G_2E:
+ check_dspr2(ctx);
switch (op2) {
case OPC_MUL_PH:
gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
@@ -14477,13 +14444,19 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
case OPC_XOR:
gen_logic(ctx, op1, rd, rs, rt);
break;
- case OPC_MULT ... OPC_DIVU:
+ case OPC_MULT:
+ case OPC_MULTU:
if (sa) {
check_insn(ctx, INSN_VR54XX);
op1 = MASK_MUL_VR54XX(ctx->opcode);
gen_mul_vr54xx(ctx, op1, rd, rs, rt);
- } else
- gen_muldiv(ctx, op1, rs, rt);
+ } else {
+ gen_muldiv(ctx, op1, rd & 3, rs, rt);
+ }
+ break;
+ case OPC_DIV:
+ case OPC_DIVU:
+ gen_muldiv(ctx, op1, 0, rs, rt);
break;
case OPC_JR ... OPC_JALR:
gen_compute_branch(ctx, op1, 4, rs, rd, sa);
@@ -14495,11 +14468,11 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
break;
case OPC_MFHI: /* Move from HI/LO */
case OPC_MFLO:
- gen_HILO(ctx, op1, rd);
+ gen_HILO(ctx, op1, rs & 3, rd);
break;
case OPC_MTHI:
case OPC_MTLO: /* Move to HI/LO */
- gen_HILO(ctx, op1, rs);
+ gen_HILO(ctx, op1, rd & 3, rs);
break;
case OPC_PMON: /* Pmon entry point, also R4010 selsl */
#ifdef MIPS_STRICT_STANDARD
@@ -14619,7 +14592,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
case OPC_DMULT ... OPC_DDIVU:
check_insn(ctx, ISA_MIPS3);
check_mips_64(ctx);
- gen_muldiv(ctx, op1, rs, rt);
+ gen_muldiv(ctx, op1, 0, rs, rt);
break;
#endif
default: /* Invalid */
@@ -14634,7 +14607,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
case OPC_MSUB ... OPC_MSUBU:
check_insn(ctx, ISA_MIPS32);
- gen_muldiv(ctx, op1, rs, rt);
+ gen_muldiv(ctx, op1, rd & 3, rs, rt);
break;
case OPC_MUL:
gen_arith(ctx, op1, rd, rs, rt);
@@ -15604,7 +15577,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
if (max_insns == 0)
max_insns = CF_COUNT_MASK;
LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
- gen_icount_start();
+ gen_tb_start();
while (ctx.bstate == BS_NONE) {
if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
@@ -15702,7 +15675,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
}
}
done_generating:
- gen_icount_end(tb, num_insns);
+ gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
@@ -15836,7 +15809,7 @@ void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
#endif
}
-static void mips_tcg_init(void)
+void mips_tcg_init(void)
{
int i;
static int inited;
@@ -15915,9 +15888,9 @@ MIPSCPU *cpu_mips_init(const char *cpu_model)
#endif
fpu_init(env, def);
mvp_init(env, def);
- mips_tcg_init();
- cpu_reset(CPU(cpu));
- qemu_init_vcpu(env);
+
+ object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
+
return cpu;
}
@@ -15972,6 +15945,14 @@ void cpu_state_reset(CPUMIPSState *env)
#if defined(CONFIG_USER_ONLY)
env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
+# ifdef TARGET_MIPS64
+ /* Enable 64-bit register mode. */
+ env->CP0_Status |= (1 << CP0St_PX);
+# endif
+# ifdef TARGET_ABI_MIPSN64
+ /* Enable 64-bit address mode. */
+ env->CP0_Status |= (1 << CP0St_UX);
+# endif
/* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
hardware registers. */
env->CP0_HWREna |= 0x0000000F;
@@ -15981,6 +15962,10 @@ void cpu_state_reset(CPUMIPSState *env)
if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
env->CP0_Status |= (1 << CP0St_MX);
}
+ /* Enable 64-bit FPU if the target cpu supports it. */
+ if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
+ env->CP0_Status |= (1 << CP0St_FR);
+ }
#else
if (env->hflags & MIPS_HFLAG_BMASK) {
/* If the exception was raised from a delay slot,
@@ -16020,7 +16005,7 @@ void cpu_state_reset(CPUMIPSState *env)
env->tcs[i].CP0_TCHalt = 1;
}
env->active_tc.CP0_TCHalt = 1;
- env->halted = 1;
+ cs->halted = 1;
if (cs->cpu_index == 0) {
/* VPE0 starts up enabled. */
@@ -16028,7 +16013,7 @@ void cpu_state_reset(CPUMIPSState *env)
env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
/* TC0 starts up unhalted. */
- env->halted = 0;
+ cs->halted = 0;
env->active_tc.CP0_TCHalt = 0;
env->tcs[0].CP0_TCHalt = 0;
/* With thread 0 active. */