diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/i386/cpu.c | 3 | ||||
-rw-r--r-- | target/i386/cpu.h | 1 | ||||
-rw-r--r-- | target/mips/dsp_helper.c | 40 | ||||
-rw-r--r-- | target/mips/lmi_helper.c | 8 | ||||
-rw-r--r-- | target/mips/msa_helper.c | 542 | ||||
-rw-r--r-- | target/mips/translate.c | 152 | ||||
-rw-r--r-- | target/ppc/helper.h | 12 | ||||
-rw-r--r-- | target/ppc/int_helper.c | 53 | ||||
-rw-r--r-- | target/ppc/kvm.c | 9 | ||||
-rw-r--r-- | target/ppc/kvm_ppc.h | 6 | ||||
-rw-r--r-- | target/ppc/trace-events | 2 | ||||
-rw-r--r-- | target/ppc/translate/vmx-impl.inc.c | 24 | ||||
-rw-r--r-- | target/ppc/translate/vsx-impl.inc.c | 86 |
13 files changed, 722 insertions, 216 deletions
diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 536d7d1520..c1ab86d63e 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -4730,6 +4730,9 @@ static void x86_cpu_reset(CPUState *s) env->pat = 0x0007040600070406ULL; env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT; + if (env->features[FEAT_1_ECX] & CPUID_EXT_MONITOR) { + env->msr_ia32_misc_enable |= MSR_IA32_MISC_ENABLE_MWAIT; + } memset(env->dr, 0, sizeof(env->dr)); env->dr[6] = DR6_FIXED_1; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index fce6660bac..bd06523a53 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -387,6 +387,7 @@ typedef enum X86Seg { #define MSR_IA32_MISC_ENABLE 0x1a0 /* Indicates good rep/movs microcode on some processors: */ #define MSR_IA32_MISC_ENABLE_DEFAULT 1 +#define MSR_IA32_MISC_ENABLE_MWAIT (1ULL << 18) #define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg)) #define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1) diff --git a/target/mips/dsp_helper.c b/target/mips/dsp_helper.c index 739b69dd45..8c58eeb0bf 100644 --- a/target/mips/dsp_helper.c +++ b/target/mips/dsp_helper.c @@ -22,8 +22,10 @@ #include "exec/helper-proto.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. */ +/* + * As the byte ordering doesn't matter, i.e. all columns are treated + * identically, these unions can be used directly. + */ typedef union { uint8_t ub[4]; int8_t sb[4]; @@ -1445,9 +1447,15 @@ target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt) return temp; } -#define PRECR_QH_PW(name, var) \ -target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \ - uint32_t sa) \ + +/* + * In case sa == 0, use rt2, rt0, rs2, rs0. + * In case sa != 0, use rt3, rt1, rs3, rs1. + */ +#define PRECR_QH_PW(name, var) \ +target_ulong helper_precr_##name##_qh_pw(target_ulong rs, \ + target_ulong rt, \ + uint32_t sa) \ { \ uint16_t rs3, rs2, rs1, rs0; \ uint16_t rt3, rt2, rt1, rt0; \ @@ -1456,8 +1464,6 @@ target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \ MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \ MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ \ - /* When sa = 0, we use rt2, rt0, rs2, rs0; \ - * when sa != 0, we use rt3, rt1, rs3, rs1. */ \ if (sa == 0) { \ tempD = rt2 << var; \ tempC = rt0 << var; \ @@ -1965,7 +1971,8 @@ SHIFT_PH(shra_r, rnd16_rashift); #undef SHIFT_PH /** DSP Multiply Sub-class insns **/ -/* Return value made up by two 16bits value. +/* + * Return value made up by two 16bits value. * FIXME give the macro a better name. */ #define MUL_RETURN32_16_PH(name, func, \ @@ -3274,11 +3281,15 @@ target_ulong helper_dextr_l(target_ulong ac, target_ulong shift, CPUMIPSState *env) { uint64_t temp[3]; + target_ulong ret; shift = shift & 0x3F; mipsdsp_rndrashift_acc(temp, ac, shift, env); - return (temp[1] << 63) | (temp[0] >> 1); + + ret = (temp[1] << 63) | (temp[0] >> 1); + + return ret; } target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift, @@ -3286,6 +3297,7 @@ target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift, { uint64_t temp[3]; uint32_t temp128; + target_ulong ret; shift = shift & 0x3F; mipsdsp_rndrashift_acc(temp, ac, shift, env); @@ -3305,7 +3317,9 @@ target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift, set_DSPControl_overflow_flag(1, 23, env); } - return (temp[1] << 63) | (temp[0] >> 1); + ret = (temp[1] << 63) | (temp[0] >> 1); + + return ret; } target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift, @@ -3313,6 +3327,7 @@ target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift, { uint64_t temp[3]; uint32_t temp128; + target_ulong ret; shift = shift & 0x3F; mipsdsp_rndrashift_acc(temp, ac, shift, env); @@ -3338,7 +3353,10 @@ target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift, } set_DSPControl_overflow_flag(1, 23, env); } - return (temp[1] << 63) | (temp[0] >> 1); + + ret = (temp[1] << 63) | (temp[0] >> 1); + + return ret; } #endif diff --git a/target/mips/lmi_helper.c b/target/mips/lmi_helper.c index fb1245b39d..6c645cf679 100644 --- a/target/mips/lmi_helper.c +++ b/target/mips/lmi_helper.c @@ -21,9 +21,11 @@ #include "cpu.h" #include "exec/helper-proto.h" -/* If the byte ordering doesn't matter, i.e. all columns are treated - identically, then this union can be used directly. If byte ordering - does matter, we generally ignore dumping to memory. */ +/* + * If the byte ordering doesn't matter, i.e. all columns are treated + * identically, then this union can be used directly. If byte ordering + * does matter, we generally ignore dumping to memory. + */ typedef union { uint8_t ub[8]; int8_t sb[8]; diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index ee1b1fa5f5..f6e16c2405 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -805,28 +805,45 @@ void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \ wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \ - uint32_t i; \ \ switch (df) { \ case DF_BYTE: \ - for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \ - pwd->b[i] = msa_ ## func ## _df(df, pws->b[i], pwt->b[i]); \ - } \ + pwd->b[0] = msa_ ## func ## _df(df, pws->b[0], pwt->b[0]); \ + pwd->b[1] = msa_ ## func ## _df(df, pws->b[1], pwt->b[1]); \ + pwd->b[2] = msa_ ## func ## _df(df, pws->b[2], pwt->b[2]); \ + pwd->b[3] = msa_ ## func ## _df(df, pws->b[3], pwt->b[3]); \ + pwd->b[4] = msa_ ## func ## _df(df, pws->b[4], pwt->b[4]); \ + pwd->b[5] = msa_ ## func ## _df(df, pws->b[5], pwt->b[5]); \ + pwd->b[6] = msa_ ## func ## _df(df, pws->b[6], pwt->b[6]); \ + pwd->b[7] = msa_ ## func ## _df(df, pws->b[7], pwt->b[7]); \ + pwd->b[8] = msa_ ## func ## _df(df, pws->b[8], pwt->b[8]); \ + pwd->b[9] = msa_ ## func ## _df(df, pws->b[9], pwt->b[9]); \ + pwd->b[10] = msa_ ## func ## _df(df, pws->b[10], pwt->b[10]); \ + pwd->b[11] = msa_ ## func ## _df(df, pws->b[11], pwt->b[11]); \ + pwd->b[12] = msa_ ## func ## _df(df, pws->b[12], pwt->b[12]); \ + pwd->b[13] = msa_ ## func ## _df(df, pws->b[13], pwt->b[13]); \ + pwd->b[14] = msa_ ## func ## _df(df, pws->b[14], pwt->b[14]); \ + pwd->b[15] = msa_ ## func ## _df(df, pws->b[15], pwt->b[15]); \ break; \ case DF_HALF: \ - for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \ - pwd->h[i] = msa_ ## func ## _df(df, pws->h[i], pwt->h[i]); \ - } \ + pwd->h[0] = msa_ ## func ## _df(df, pws->h[0], pwt->h[0]); \ + pwd->h[1] = msa_ ## func ## _df(df, pws->h[1], pwt->h[1]); \ + pwd->h[2] = msa_ ## func ## _df(df, pws->h[2], pwt->h[2]); \ + pwd->h[3] = msa_ ## func ## _df(df, pws->h[3], pwt->h[3]); \ + pwd->h[4] = msa_ ## func ## _df(df, pws->h[4], pwt->h[4]); \ + pwd->h[5] = msa_ ## func ## _df(df, pws->h[5], pwt->h[5]); \ + pwd->h[6] = msa_ ## func ## _df(df, pws->h[6], pwt->h[6]); \ + pwd->h[7] = msa_ ## func ## _df(df, pws->h[7], pwt->h[7]); \ break; \ case DF_WORD: \ - for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \ - pwd->w[i] = msa_ ## func ## _df(df, pws->w[i], pwt->w[i]); \ - } \ + pwd->w[0] = msa_ ## func ## _df(df, pws->w[0], pwt->w[0]); \ + pwd->w[1] = msa_ ## func ## _df(df, pws->w[1], pwt->w[1]); \ + pwd->w[2] = msa_ ## func ## _df(df, pws->w[2], pwt->w[2]); \ + pwd->w[3] = msa_ ## func ## _df(df, pws->w[3], pwt->w[3]); \ break; \ case DF_DOUBLE: \ - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \ - pwd->d[i] = msa_ ## func ## _df(df, pws->d[i], pwt->d[i]); \ - } \ + pwd->d[0] = msa_ ## func ## _df(df, pws->d[0], pwt->d[0]); \ + pwd->d[1] = msa_ ## func ## _df(df, pws->d[1], pwt->d[1]); \ break; \ default: \ assert(0); \ @@ -1012,42 +1029,71 @@ static inline int64_t msa_msubr_q_df(uint32_t df, int64_t dest, int64_t arg1, } #define MSA_TEROP_DF(func) \ -void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, uint32_t wd, \ - uint32_t ws, uint32_t wt) \ -{ \ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ - wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ - wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \ - uint32_t i; \ - \ - switch (df) { \ - case DF_BYTE: \ - for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \ - pwd->b[i] = msa_ ## func ## _df(df, pwd->b[i], pws->b[i], \ - pwt->b[i]); \ - } \ - break; \ - case DF_HALF: \ - for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \ - pwd->h[i] = msa_ ## func ## _df(df, pwd->h[i], pws->h[i], \ - pwt->h[i]); \ - } \ - break; \ - case DF_WORD: \ - for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \ - pwd->w[i] = msa_ ## func ## _df(df, pwd->w[i], pws->w[i], \ - pwt->w[i]); \ - } \ - break; \ - case DF_DOUBLE: \ - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \ - pwd->d[i] = msa_ ## func ## _df(df, pwd->d[i], pws->d[i], \ - pwt->d[i]); \ - } \ - break; \ - default: \ - assert(0); \ - } \ +void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, uint32_t wd, \ + uint32_t ws, uint32_t wt) \ +{ \ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ + wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \ + \ + switch (df) { \ + case DF_BYTE: \ + pwd->b[0] = msa_ ## func ## _df(df, pwd->b[0], pws->b[0], \ + pwt->b[0]); \ + pwd->b[1] = msa_ ## func ## _df(df, pwd->b[1], pws->b[1], \ + pwt->b[1]); \ + pwd->b[2] = msa_ ## func ## _df(df, pwd->b[2], pws->b[2], \ + pwt->b[2]); \ + pwd->b[3] = msa_ ## func ## _df(df, pwd->b[3], pws->b[3], \ + pwt->b[3]); \ + pwd->b[4] = msa_ ## func ## _df(df, pwd->b[4], pws->b[4], \ + pwt->b[4]); \ + pwd->b[5] = msa_ ## func ## _df(df, pwd->b[5], pws->b[5], \ + pwt->b[5]); \ + pwd->b[6] = msa_ ## func ## _df(df, pwd->b[6], pws->b[6], \ + pwt->b[6]); \ + pwd->b[7] = msa_ ## func ## _df(df, pwd->b[7], pws->b[7], \ + pwt->b[7]); \ + pwd->b[8] = msa_ ## func ## _df(df, pwd->b[8], pws->b[8], \ + pwt->b[8]); \ + pwd->b[9] = msa_ ## func ## _df(df, pwd->b[9], pws->b[9], \ + pwt->b[9]); \ + pwd->b[10] = msa_ ## func ## _df(df, pwd->b[10], pws->b[10], \ + pwt->b[10]); \ + pwd->b[11] = msa_ ## func ## _df(df, pwd->b[11], pws->b[11], \ + pwt->b[11]); \ + pwd->b[12] = msa_ ## func ## _df(df, pwd->b[12], pws->b[12], \ + pwt->b[12]); \ + pwd->b[13] = msa_ ## func ## _df(df, pwd->b[13], pws->b[13], \ + pwt->b[13]); \ + pwd->b[14] = msa_ ## func ## _df(df, pwd->b[14], pws->b[14], \ + pwt->b[14]); \ + pwd->b[15] = msa_ ## func ## _df(df, pwd->b[15], pws->b[15], \ + pwt->b[15]); \ + break; \ + case DF_HALF: \ + pwd->h[0] = msa_ ## func ## _df(df, pwd->h[0], pws->h[0], pwt->h[0]); \ + pwd->h[1] = msa_ ## func ## _df(df, pwd->h[1], pws->h[1], pwt->h[1]); \ + pwd->h[2] = msa_ ## func ## _df(df, pwd->h[2], pws->h[2], pwt->h[2]); \ + pwd->h[3] = msa_ ## func ## _df(df, pwd->h[3], pws->h[3], pwt->h[3]); \ + pwd->h[4] = msa_ ## func ## _df(df, pwd->h[4], pws->h[4], pwt->h[4]); \ + pwd->h[5] = msa_ ## func ## _df(df, pwd->h[5], pws->h[5], pwt->h[5]); \ + pwd->h[6] = msa_ ## func ## _df(df, pwd->h[6], pws->h[6], pwt->h[6]); \ + pwd->h[7] = msa_ ## func ## _df(df, pwd->h[7], pws->h[7], pwt->h[7]); \ + break; \ + case DF_WORD: \ + pwd->w[0] = msa_ ## func ## _df(df, pwd->w[0], pws->w[0], pwt->w[0]); \ + pwd->w[1] = msa_ ## func ## _df(df, pwd->w[1], pws->w[1], pwt->w[1]); \ + pwd->w[2] = msa_ ## func ## _df(df, pwd->w[2], pws->w[2], pwt->w[2]); \ + pwd->w[3] = msa_ ## func ## _df(df, pwd->w[3], pws->w[3], pwt->w[3]); \ + break; \ + case DF_DOUBLE: \ + pwd->d[0] = msa_ ## func ## _df(df, pwd->d[0], pws->d[0], pwt->d[0]); \ + pwd->d[1] = msa_ ## func ## _df(df, pwd->d[1], pws->d[1], pwt->d[1]); \ + break; \ + default: \ + assert(0); \ + } \ } MSA_TEROP_DF(maddv) @@ -1167,53 +1213,6 @@ void helper_msa_##FUNC(CPUMIPSState *env, uint32_t df, uint32_t wd, \ #define Rd(pwr, i) (pwr->d[i]) #define Ld(pwr, i) (pwr->d[i + DF_ELEMENTS(DF_DOUBLE)/2]) -#define MSA_DO(DF) \ - do { \ - R##DF(pwx, i) = pwt->DF[2*i]; \ - L##DF(pwx, i) = pws->DF[2*i]; \ - } while (0) -MSA_FN_DF(pckev_df) -#undef MSA_DO - -#define MSA_DO(DF) \ - do { \ - R##DF(pwx, i) = pwt->DF[2*i+1]; \ - L##DF(pwx, i) = pws->DF[2*i+1]; \ - } while (0) -MSA_FN_DF(pckod_df) -#undef MSA_DO - -#define MSA_DO(DF) \ - do { \ - pwx->DF[2*i] = L##DF(pwt, i); \ - pwx->DF[2*i+1] = L##DF(pws, i); \ - } while (0) -MSA_FN_DF(ilvl_df) -#undef MSA_DO - -#define MSA_DO(DF) \ - do { \ - pwx->DF[2*i] = R##DF(pwt, i); \ - pwx->DF[2*i+1] = R##DF(pws, i); \ - } while (0) -MSA_FN_DF(ilvr_df) -#undef MSA_DO - -#define MSA_DO(DF) \ - do { \ - pwx->DF[2*i] = pwt->DF[2*i]; \ - pwx->DF[2*i+1] = pws->DF[2*i]; \ - } while (0) -MSA_FN_DF(ilvev_df) -#undef MSA_DO - -#define MSA_DO(DF) \ - do { \ - pwx->DF[2*i] = pwt->DF[2*i+1]; \ - pwx->DF[2*i+1] = pws->DF[2*i+1]; \ - } while (0) -MSA_FN_DF(ilvod_df) -#undef MSA_DO #undef MSA_LOOP_COND #define MSA_LOOP_COND(DF) \ @@ -1231,6 +1230,314 @@ MSA_FN_DF(vshf_df) #undef MSA_LOOP_COND #undef MSA_FN_DF + +void helper_msa_ilvev_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + switch (df) { + case DF_BYTE: + pwd->b[15] = pws->b[14]; + pwd->b[14] = pwt->b[14]; + pwd->b[13] = pws->b[12]; + pwd->b[12] = pwt->b[12]; + pwd->b[11] = pws->b[10]; + pwd->b[10] = pwt->b[10]; + pwd->b[9] = pws->b[8]; + pwd->b[8] = pwt->b[8]; + pwd->b[7] = pws->b[6]; + pwd->b[6] = pwt->b[6]; + pwd->b[5] = pws->b[4]; + pwd->b[4] = pwt->b[4]; + pwd->b[3] = pws->b[2]; + pwd->b[2] = pwt->b[2]; + pwd->b[1] = pws->b[0]; + pwd->b[0] = pwt->b[0]; + break; + case DF_HALF: + pwd->h[7] = pws->h[6]; + pwd->h[6] = pwt->h[6]; + pwd->h[5] = pws->h[4]; + pwd->h[4] = pwt->h[4]; + pwd->h[3] = pws->h[2]; + pwd->h[2] = pwt->h[2]; + pwd->h[1] = pws->h[0]; + pwd->h[0] = pwt->h[0]; + break; + case DF_WORD: + pwd->w[3] = pws->w[2]; + pwd->w[2] = pwt->w[2]; + pwd->w[1] = pws->w[0]; + pwd->w[0] = pwt->w[0]; + break; + case DF_DOUBLE: + pwd->d[1] = pws->d[0]; + pwd->d[0] = pwt->d[0]; + break; + default: + assert(0); + } +} + +void helper_msa_ilvod_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + switch (df) { + case DF_BYTE: + pwd->b[0] = pwt->b[1]; + pwd->b[1] = pws->b[1]; + pwd->b[2] = pwt->b[3]; + pwd->b[3] = pws->b[3]; + pwd->b[4] = pwt->b[5]; + pwd->b[5] = pws->b[5]; + pwd->b[6] = pwt->b[7]; + pwd->b[7] = pws->b[7]; + pwd->b[8] = pwt->b[9]; + pwd->b[9] = pws->b[9]; + pwd->b[10] = pwt->b[11]; + pwd->b[11] = pws->b[11]; + pwd->b[12] = pwt->b[13]; + pwd->b[13] = pws->b[13]; + pwd->b[14] = pwt->b[15]; + pwd->b[15] = pws->b[15]; + break; + case DF_HALF: + pwd->h[0] = pwt->h[1]; + pwd->h[1] = pws->h[1]; + pwd->h[2] = pwt->h[3]; + pwd->h[3] = pws->h[3]; + pwd->h[4] = pwt->h[5]; + pwd->h[5] = pws->h[5]; + pwd->h[6] = pwt->h[7]; + pwd->h[7] = pws->h[7]; + break; + case DF_WORD: + pwd->w[0] = pwt->w[1]; + pwd->w[1] = pws->w[1]; + pwd->w[2] = pwt->w[3]; + pwd->w[3] = pws->w[3]; + break; + case DF_DOUBLE: + pwd->d[0] = pwt->d[1]; + pwd->d[1] = pws->d[1]; + break; + default: + assert(0); + } +} + +void helper_msa_ilvl_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + switch (df) { + case DF_BYTE: + pwd->b[0] = pwt->b[8]; + pwd->b[1] = pws->b[8]; + pwd->b[2] = pwt->b[9]; + pwd->b[3] = pws->b[9]; + pwd->b[4] = pwt->b[10]; + pwd->b[5] = pws->b[10]; + pwd->b[6] = pwt->b[11]; + pwd->b[7] = pws->b[11]; + pwd->b[8] = pwt->b[12]; + pwd->b[9] = pws->b[12]; + pwd->b[10] = pwt->b[13]; + pwd->b[11] = pws->b[13]; + pwd->b[12] = pwt->b[14]; + pwd->b[13] = pws->b[14]; + pwd->b[14] = pwt->b[15]; + pwd->b[15] = pws->b[15]; + break; + case DF_HALF: + pwd->h[0] = pwt->h[4]; + pwd->h[1] = pws->h[4]; + pwd->h[2] = pwt->h[5]; + pwd->h[3] = pws->h[5]; + pwd->h[4] = pwt->h[6]; + pwd->h[5] = pws->h[6]; + pwd->h[6] = pwt->h[7]; + pwd->h[7] = pws->h[7]; + break; + case DF_WORD: + pwd->w[0] = pwt->w[2]; + pwd->w[1] = pws->w[2]; + pwd->w[2] = pwt->w[3]; + pwd->w[3] = pws->w[3]; + break; + case DF_DOUBLE: + pwd->d[0] = pwt->d[1]; + pwd->d[1] = pws->d[1]; + break; + default: + assert(0); + } +} + +void helper_msa_ilvr_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + switch (df) { + case DF_BYTE: + pwd->b[15] = pws->b[7]; + pwd->b[14] = pwt->b[7]; + pwd->b[13] = pws->b[6]; + pwd->b[12] = pwt->b[6]; + pwd->b[11] = pws->b[5]; + pwd->b[10] = pwt->b[5]; + pwd->b[9] = pws->b[4]; + pwd->b[8] = pwt->b[4]; + pwd->b[7] = pws->b[3]; + pwd->b[6] = pwt->b[3]; + pwd->b[5] = pws->b[2]; + pwd->b[4] = pwt->b[2]; + pwd->b[3] = pws->b[1]; + pwd->b[2] = pwt->b[1]; + pwd->b[1] = pws->b[0]; + pwd->b[0] = pwt->b[0]; + break; + case DF_HALF: + pwd->h[7] = pws->h[3]; + pwd->h[6] = pwt->h[3]; + pwd->h[5] = pws->h[2]; + pwd->h[4] = pwt->h[2]; + pwd->h[3] = pws->h[1]; + pwd->h[2] = pwt->h[1]; + pwd->h[1] = pws->h[0]; + pwd->h[0] = pwt->h[0]; + break; + case DF_WORD: + pwd->w[3] = pws->w[1]; + pwd->w[2] = pwt->w[1]; + pwd->w[1] = pws->w[0]; + pwd->w[0] = pwt->w[0]; + break; + case DF_DOUBLE: + pwd->d[1] = pws->d[0]; + pwd->d[0] = pwt->d[0]; + break; + default: + assert(0); + } +} + +void helper_msa_pckev_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + switch (df) { + case DF_BYTE: + pwd->b[15] = pws->b[14]; + pwd->b[13] = pws->b[10]; + pwd->b[11] = pws->b[6]; + pwd->b[9] = pws->b[2]; + pwd->b[7] = pwt->b[14]; + pwd->b[5] = pwt->b[10]; + pwd->b[3] = pwt->b[6]; + pwd->b[1] = pwt->b[2]; + pwd->b[14] = pws->b[12]; + pwd->b[10] = pws->b[4]; + pwd->b[6] = pwt->b[12]; + pwd->b[2] = pwt->b[4]; + pwd->b[12] = pws->b[8]; + pwd->b[4] = pwt->b[8]; + pwd->b[8] = pws->b[0]; + pwd->b[0] = pwt->b[0]; + break; + case DF_HALF: + pwd->h[7] = pws->h[6]; + pwd->h[5] = pws->h[2]; + pwd->h[3] = pwt->h[6]; + pwd->h[1] = pwt->h[2]; + pwd->h[6] = pws->h[4]; + pwd->h[2] = pwt->h[4]; + pwd->h[4] = pws->h[0]; + pwd->h[0] = pwt->h[0]; + break; + case DF_WORD: + pwd->w[3] = pws->w[2]; + pwd->w[1] = pwt->w[2]; + pwd->w[2] = pws->w[0]; + pwd->w[0] = pwt->w[0]; + break; + case DF_DOUBLE: + pwd->d[1] = pws->d[0]; + pwd->d[0] = pwt->d[0]; + break; + default: + assert(0); + } +} + +void helper_msa_pckod_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + switch (df) { + case DF_BYTE: + pwd->b[0] = pwt->b[1]; + pwd->b[2] = pwt->b[5]; + pwd->b[4] = pwt->b[9]; + pwd->b[6] = pwt->b[13]; + pwd->b[8] = pws->b[1]; + pwd->b[10] = pws->b[5]; + pwd->b[12] = pws->b[9]; + pwd->b[14] = pws->b[13]; + pwd->b[1] = pwt->b[3]; + pwd->b[5] = pwt->b[11]; + pwd->b[9] = pws->b[3]; + pwd->b[13] = pws->b[11]; + pwd->b[3] = pwt->b[7]; + pwd->b[11] = pws->b[7]; + pwd->b[7] = pwt->b[15]; + pwd->b[15] = pws->b[15]; + break; + case DF_HALF: + pwd->h[0] = pwt->h[1]; + pwd->h[2] = pwt->h[5]; + pwd->h[4] = pws->h[1]; + pwd->h[6] = pws->h[5]; + pwd->h[1] = pwt->h[3]; + pwd->h[5] = pws->h[3]; + pwd->h[3] = pwt->h[7]; + pwd->h[7] = pws->h[7]; + break; + case DF_WORD: + pwd->w[0] = pwt->w[1]; + pwd->w[2] = pws->w[1]; + pwd->w[1] = pwt->w[3]; + pwd->w[3] = pws->w[3]; + break; + case DF_DOUBLE: + pwd->d[0] = pwt->d[1]; + pwd->d[1] = pws->d[1]; + break; + default: + assert(0); + } +} + + void helper_msa_sldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t ws, uint32_t n) { @@ -1537,28 +1844,45 @@ void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \ { \ wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ - uint32_t i; \ \ switch (df) { \ case DF_BYTE: \ - for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \ - pwd->b[i] = msa_ ## func ## _df(df, pws->b[i]); \ - } \ + pwd->b[0] = msa_ ## func ## _df(df, pws->b[0]); \ + pwd->b[1] = msa_ ## func ## _df(df, pws->b[1]); \ + pwd->b[2] = msa_ ## func ## _df(df, pws->b[2]); \ + pwd->b[3] = msa_ ## func ## _df(df, pws->b[3]); \ + pwd->b[4] = msa_ ## func ## _df(df, pws->b[4]); \ + pwd->b[5] = msa_ ## func ## _df(df, pws->b[5]); \ + pwd->b[6] = msa_ ## func ## _df(df, pws->b[6]); \ + pwd->b[7] = msa_ ## func ## _df(df, pws->b[7]); \ + pwd->b[8] = msa_ ## func ## _df(df, pws->b[8]); \ + pwd->b[9] = msa_ ## func ## _df(df, pws->b[9]); \ + pwd->b[10] = msa_ ## func ## _df(df, pws->b[10]); \ + pwd->b[11] = msa_ ## func ## _df(df, pws->b[11]); \ + pwd->b[12] = msa_ ## func ## _df(df, pws->b[12]); \ + pwd->b[13] = msa_ ## func ## _df(df, pws->b[13]); \ + pwd->b[14] = msa_ ## func ## _df(df, pws->b[14]); \ + pwd->b[15] = msa_ ## func ## _df(df, pws->b[15]); \ break; \ case DF_HALF: \ - for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \ - pwd->h[i] = msa_ ## func ## _df(df, pws->h[i]); \ - } \ + pwd->h[0] = msa_ ## func ## _df(df, pws->h[0]); \ + pwd->h[1] = msa_ ## func ## _df(df, pws->h[1]); \ + pwd->h[2] = msa_ ## func ## _df(df, pws->h[2]); \ + pwd->h[3] = msa_ ## func ## _df(df, pws->h[3]); \ + pwd->h[4] = msa_ ## func ## _df(df, pws->h[4]); \ + pwd->h[5] = msa_ ## func ## _df(df, pws->h[5]); \ + pwd->h[6] = msa_ ## func ## _df(df, pws->h[6]); \ + pwd->h[7] = msa_ ## func ## _df(df, pws->h[7]); \ break; \ case DF_WORD: \ - for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \ - pwd->w[i] = msa_ ## func ## _df(df, pws->w[i]); \ - } \ + pwd->w[0] = msa_ ## func ## _df(df, pws->w[0]); \ + pwd->w[1] = msa_ ## func ## _df(df, pws->w[1]); \ + pwd->w[2] = msa_ ## func ## _df(df, pws->w[2]); \ + pwd->w[3] = msa_ ## func ## _df(df, pws->w[3]); \ break; \ case DF_DOUBLE: \ - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \ - pwd->d[i] = msa_ ## func ## _df(df, pws->d[i]); \ - } \ + pwd->d[0] = msa_ ## func ## _df(df, pws->d[0]); \ + pwd->d[1] = msa_ ## func ## _df(df, pws->d[1]); \ break; \ default: \ assert(0); \ diff --git a/target/mips/translate.c b/target/mips/translate.c index 70552fe543..e37722dfff 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -24357,6 +24357,146 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) * PEXTUW */ +/* + * PCPYH rd, rt + * + * Parallel Copy Halfword + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---------+---------+-----------+ + * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 | + * +-----------+---------+---------+---------+---------+-----------+ + */ +static void gen_mmi_pcpyh(DisasContext *ctx) +{ + uint32_t pd, rt, rd; + uint32_t opcode; + + opcode = ctx->opcode; + + pd = extract32(opcode, 21, 5); + rt = extract32(opcode, 16, 5); + rd = extract32(opcode, 11, 5); + + if (unlikely(pd != 0)) { + generate_exception_end(ctx, EXCP_RI); + } else if (rd == 0) { + /* nop */ + } else if (rt == 0) { + tcg_gen_movi_i64(cpu_gpr[rd], 0); + tcg_gen_movi_i64(cpu_mmr[rd], 0); + } else { + TCGv_i64 t0 = tcg_temp_new(); + TCGv_i64 t1 = tcg_temp_new(); + uint64_t mask = (1ULL << 16) - 1; + + tcg_gen_andi_i64(t0, cpu_gpr[rt], mask); + tcg_gen_movi_i64(t1, 0); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + + tcg_gen_mov_i64(cpu_gpr[rd], t1); + + tcg_gen_andi_i64(t0, cpu_mmr[rt], mask); + tcg_gen_movi_i64(t1, 0); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + + tcg_gen_mov_i64(cpu_mmr[rd], t1); + + tcg_temp_free(t0); + tcg_temp_free(t1); + } +} + +/* + * PCPYLD rd, rs, rt + * + * Parallel Copy Lower Doubleword + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---------+---------+-----------+ + * | MMI | rs | rt | rd | PCPYLD | MMI2 | + * +-----------+---------+---------+---------+---------+-----------+ + */ +static void gen_mmi_pcpyld(DisasContext *ctx) +{ + uint32_t rs, rt, rd; + uint32_t opcode; + + opcode = ctx->opcode; + + rs = extract32(opcode, 21, 5); + rt = extract32(opcode, 16, 5); + rd = extract32(opcode, 11, 5); + + if (rd == 0) { + /* nop */ + } else { + if (rs == 0) { + tcg_gen_movi_i64(cpu_mmr[rd], 0); + } else { + tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]); + } + if (rt == 0) { + tcg_gen_movi_i64(cpu_gpr[rd], 0); + } else { + if (rd != rt) { + tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]); + } + } + } +} + +/* + * PCPYUD rd, rs, rt + * + * Parallel Copy Upper Doubleword + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---------+---------+-----------+ + * | MMI | rs | rt | rd | PCPYUD | MMI3 | + * +-----------+---------+---------+---------+---------+-----------+ + */ +static void gen_mmi_pcpyud(DisasContext *ctx) +{ + uint32_t rs, rt, rd; + uint32_t opcode; + + opcode = ctx->opcode; + + rs = extract32(opcode, 21, 5); + rt = extract32(opcode, 16, 5); + rd = extract32(opcode, 11, 5); + + if (rd == 0) { + /* nop */ + } else { + if (rs == 0) { + tcg_gen_movi_i64(cpu_gpr[rd], 0); + } else { + tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]); + } + if (rt == 0) { + tcg_gen_movi_i64(cpu_mmr[rd], 0); + } else { + if (rd != rt) { + tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]); + } + } + } +} + #endif @@ -27371,7 +27511,6 @@ static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx) case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */ case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */ case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */ - case MMI_OPC_2_PCPYLD: /* TODO: MMI_OPC_2_PCPYLD */ case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */ case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */ case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */ @@ -27386,6 +27525,9 @@ static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx) case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */ generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */ break; + case MMI_OPC_2_PCPYLD: + gen_mmi_pcpyld(ctx); + break; default: MIPS_INVAL("TX79 MMI class MMI2"); generate_exception_end(ctx, EXCP_RI); @@ -27405,14 +27547,18 @@ static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx) case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */ case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */ case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */ - case MMI_OPC_3_PCPYUD: /* TODO: MMI_OPC_3_PCPYUD */ case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */ case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */ case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */ - case MMI_OPC_3_PCPYH: /* TODO: MMI_OPC_3_PCPYH */ case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */ generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */ break; + case MMI_OPC_3_PCPYH: + gen_mmi_pcpyh(ctx); + break; + case MMI_OPC_3_PCPYUD: + gen_mmi_pcpyud(ctx); + break; default: MIPS_INVAL("TX79 MMI class MMI3"); generate_exception_end(ctx, EXCP_RI); diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 638a6e99c4..02b67a333e 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -180,18 +180,6 @@ DEF_HELPER_3(vmuloub, void, avr, avr, avr) DEF_HELPER_3(vmulouh, void, avr, avr, avr) DEF_HELPER_3(vmulouw, void, avr, avr, avr) DEF_HELPER_3(vmuluwm, void, avr, avr, avr) -DEF_HELPER_3(vsrab, void, avr, avr, avr) -DEF_HELPER_3(vsrah, void, avr, avr, avr) -DEF_HELPER_3(vsraw, void, avr, avr, avr) -DEF_HELPER_3(vsrad, void, avr, avr, avr) -DEF_HELPER_3(vsrb, void, avr, avr, avr) -DEF_HELPER_3(vsrh, void, avr, avr, avr) -DEF_HELPER_3(vsrw, void, avr, avr, avr) -DEF_HELPER_3(vsrd, void, avr, avr, avr) -DEF_HELPER_3(vslb, void, avr, avr, avr) -DEF_HELPER_3(vslh, void, avr, avr, avr) -DEF_HELPER_3(vslw, void, avr, avr, avr) -DEF_HELPER_3(vsld, void, avr, avr, avr) DEF_HELPER_3(vslo, void, avr, avr, avr) DEF_HELPER_3(vsro, void, avr, avr, avr) DEF_HELPER_3(vsrv, void, avr, avr, avr) diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index 9af779ad38..8ce89f2ad9 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -1791,23 +1791,6 @@ VSHIFT(l, 1) VSHIFT(r, 0) #undef VSHIFT -#define VSL(suffix, element, mask) \ - void helper_vsl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ - { \ - int i; \ - \ - for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ - unsigned int shift = b->element[i] & mask; \ - \ - r->element[i] = a->element[i] << shift; \ - } \ - } -VSL(b, u8, 0x7) -VSL(h, u16, 0x0F) -VSL(w, u32, 0x1F) -VSL(d, u64, 0x3F) -#undef VSL - void helper_vslv(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { int i; @@ -1815,10 +1798,10 @@ void helper_vslv(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) size = ARRAY_SIZE(r->u8); for (i = 0; i < size; i++) { - shift = b->u8[i] & 0x7; /* extract shift value */ - bytes = (a->u8[i] << 8) + /* extract adjacent bytes */ - (((i + 1) < size) ? a->u8[i + 1] : 0); - r->u8[i] = (bytes << shift) >> 8; /* shift and store result */ + shift = b->VsrB(i) & 0x7; /* extract shift value */ + bytes = (a->VsrB(i) << 8) + /* extract adjacent bytes */ + (((i + 1) < size) ? a->VsrB(i + 1) : 0); + r->VsrB(i) = (bytes << shift) >> 8; /* shift and store result */ } } @@ -1833,10 +1816,10 @@ void helper_vsrv(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) * order will guarantee that computed result is not fed back. */ for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) { - shift = b->u8[i] & 0x7; /* extract shift value */ - bytes = ((i ? a->u8[i - 1] : 0) << 8) + a->u8[i]; + shift = b->VsrB(i) & 0x7; /* extract shift value */ + bytes = ((i ? a->VsrB(i - 1) : 0) << 8) + a->VsrB(i); /* extract adjacent bytes */ - r->u8[i] = (bytes >> shift) & 0xFF; /* shift and store result */ + r->VsrB(i) = (bytes >> shift) & 0xFF; /* shift and store result */ } } @@ -1980,26 +1963,6 @@ VNEG(vnegw, s32) VNEG(vnegd, s64) #undef VNEG -#define VSR(suffix, element, mask) \ - void helper_vsr##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ - { \ - int i; \ - \ - for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ - unsigned int shift = b->element[i] & mask; \ - r->element[i] = a->element[i] >> shift; \ - } \ - } -VSR(ab, s8, 0x7) -VSR(ah, s16, 0xF) -VSR(aw, s32, 0x1F) -VSR(ad, s64, 0x3F) -VSR(b, u8, 0x7) -VSR(h, u16, 0xF) -VSR(w, u32, 0x1F) -VSR(d, u64, 0x3F) -#undef VSR - void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { int sh = (b->VsrB(0xf) >> 3) & 0xf; @@ -2053,7 +2016,7 @@ void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) for (i = 0; i < ARRAY_SIZE(r->u64); i++) { int64_t t = (int64_t)b->VsrSW(upper + i * 2); - result.VsrW(i) = 0; + result.VsrD(i) = 0; for (j = 0; j < ARRAY_SIZE(r->u64); j++) { t += a->VsrSW(2 * i + j); } diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 02e22e2017..3bf0a46c33 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -75,6 +75,7 @@ static int cap_fixup_hcalls; static int cap_htm; /* Hardware transactional memory support */ static int cap_mmu_radix; static int cap_mmu_hash_v3; +static int cap_xive; static int cap_resize_hpt; static int cap_ppc_pvr_compat; static int cap_ppc_safe_cache; @@ -146,6 +147,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) cap_htm = kvm_vm_check_extension(s, KVM_CAP_PPC_HTM); cap_mmu_radix = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_RADIX); cap_mmu_hash_v3 = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_HASH_V3); + cap_xive = kvm_vm_check_extension(s, KVM_CAP_PPC_IRQ_XIVE); cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT); kvmppc_get_cpu_characteristics(s); cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV); @@ -1721,7 +1723,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) trace_kvm_handle_dcr_write(); ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data); } else { - trace_kvm_handle_drc_read(); + trace_kvm_handle_dcr_read(); ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data); } break; @@ -2478,6 +2480,11 @@ static int parse_cap_ppc_count_cache_flush_assist(struct kvm_ppc_cpu_char c) return 0; } +bool kvmppc_has_cap_xive(void) +{ + return cap_xive; +} + static void kvmppc_get_cpu_characteristics(KVMState *s) { struct kvm_ppc_cpu_char c; diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index 22385134b4..45776cad79 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -60,6 +60,7 @@ bool kvmppc_has_cap_fixup_hcalls(void); bool kvmppc_has_cap_htm(void); bool kvmppc_has_cap_mmu_radix(void); bool kvmppc_has_cap_mmu_hash_v3(void); +bool kvmppc_has_cap_xive(void); int kvmppc_get_cap_safe_cache(void); int kvmppc_get_cap_safe_bounds_check(void); int kvmppc_get_cap_safe_indirect_branch(void); @@ -316,6 +317,11 @@ static inline bool kvmppc_has_cap_mmu_hash_v3(void) return false; } +static inline bool kvmppc_has_cap_xive(void) +{ + return false; +} + static inline int kvmppc_get_cap_safe_cache(void) { return 0; diff --git a/target/ppc/trace-events b/target/ppc/trace-events index 7b3cfe11fd..3dc6740706 100644 --- a/target/ppc/trace-events +++ b/target/ppc/trace-events @@ -22,7 +22,7 @@ kvm_failed_put_vpa(void) "Warning: Unable to set VPA information to KVM" kvm_failed_get_vpa(void) "Warning: Unable to get VPA information from KVM" kvm_injected_interrupt(int irq) "injected interrupt %d" kvm_handle_dcr_write(void) "handle dcr write" -kvm_handle_drc_read(void) "handle dcr read" +kvm_handle_dcr_read(void) "handle dcr read" kvm_handle_halt(void) "handle halt" kvm_handle_papr_hcall(void) "handle PAPR hypercall" kvm_handle_epr(void) "handle epr" diff --git a/target/ppc/translate/vmx-impl.inc.c b/target/ppc/translate/vmx-impl.inc.c index 6861f4c5b9..663275b729 100644 --- a/target/ppc/translate/vmx-impl.inc.c +++ b/target/ppc/translate/vmx-impl.inc.c @@ -530,21 +530,21 @@ GEN_VXFORM(vmuleuw, 4, 10); GEN_VXFORM(vmulesb, 4, 12); GEN_VXFORM(vmulesh, 4, 13); GEN_VXFORM(vmulesw, 4, 14); -GEN_VXFORM(vslb, 2, 4); -GEN_VXFORM(vslh, 2, 5); -GEN_VXFORM(vslw, 2, 6); +GEN_VXFORM_V(vslb, MO_8, tcg_gen_gvec_shlv, 2, 4); +GEN_VXFORM_V(vslh, MO_16, tcg_gen_gvec_shlv, 2, 5); +GEN_VXFORM_V(vslw, MO_32, tcg_gen_gvec_shlv, 2, 6); GEN_VXFORM(vrlwnm, 2, 6); GEN_VXFORM_DUAL(vslw, PPC_ALTIVEC, PPC_NONE, \ vrlwnm, PPC_NONE, PPC2_ISA300) -GEN_VXFORM(vsld, 2, 23); -GEN_VXFORM(vsrb, 2, 8); -GEN_VXFORM(vsrh, 2, 9); -GEN_VXFORM(vsrw, 2, 10); -GEN_VXFORM(vsrd, 2, 27); -GEN_VXFORM(vsrab, 2, 12); -GEN_VXFORM(vsrah, 2, 13); -GEN_VXFORM(vsraw, 2, 14); -GEN_VXFORM(vsrad, 2, 15); +GEN_VXFORM_V(vsld, MO_64, tcg_gen_gvec_shlv, 2, 23); +GEN_VXFORM_V(vsrb, MO_8, tcg_gen_gvec_shrv, 2, 8); +GEN_VXFORM_V(vsrh, MO_16, tcg_gen_gvec_shrv, 2, 9); +GEN_VXFORM_V(vsrw, MO_32, tcg_gen_gvec_shrv, 2, 10); +GEN_VXFORM_V(vsrd, MO_64, tcg_gen_gvec_shrv, 2, 27); +GEN_VXFORM_V(vsrab, MO_8, tcg_gen_gvec_sarv, 2, 12); +GEN_VXFORM_V(vsrah, MO_16, tcg_gen_gvec_sarv, 2, 13); +GEN_VXFORM_V(vsraw, MO_32, tcg_gen_gvec_sarv, 2, 14); +GEN_VXFORM_V(vsrad, MO_64, tcg_gen_gvec_sarv, 2, 15); GEN_VXFORM(vsrv, 2, 28); GEN_VXFORM(vslv, 2, 29); GEN_VXFORM(vslo, 6, 16); diff --git a/target/ppc/translate/vsx-impl.inc.c b/target/ppc/translate/vsx-impl.inc.c index 11d9b75d01..199d22da97 100644 --- a/target/ppc/translate/vsx-impl.inc.c +++ b/target/ppc/translate/vsx-impl.inc.c @@ -227,7 +227,7 @@ static void gen_lxvb16x(DisasContext *ctx) tcg_temp_free_i64(xtl); } -#define VSX_VECTOR_LOAD_STORE(name, op, indexed) \ +#define VSX_VECTOR_LOAD(name, op, indexed) \ static void gen_##name(DisasContext *ctx) \ { \ int xt; \ @@ -254,8 +254,6 @@ static void gen_##name(DisasContext *ctx) \ } \ xth = tcg_temp_new_i64(); \ xtl = tcg_temp_new_i64(); \ - get_cpu_vsrh(xth, xt); \ - get_cpu_vsrl(xtl, xt); \ gen_set_access_type(ctx, ACCESS_INT); \ EA = tcg_temp_new(); \ if (indexed) { \ @@ -281,10 +279,61 @@ static void gen_##name(DisasContext *ctx) \ tcg_temp_free_i64(xtl); \ } -VSX_VECTOR_LOAD_STORE(lxv, ld_i64, 0) -VSX_VECTOR_LOAD_STORE(stxv, st_i64, 0) -VSX_VECTOR_LOAD_STORE(lxvx, ld_i64, 1) -VSX_VECTOR_LOAD_STORE(stxvx, st_i64, 1) +VSX_VECTOR_LOAD(lxv, ld_i64, 0) +VSX_VECTOR_LOAD(lxvx, ld_i64, 1) + +#define VSX_VECTOR_STORE(name, op, indexed) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + int xt; \ + TCGv EA; \ + TCGv_i64 xth; \ + TCGv_i64 xtl; \ + \ + if (indexed) { \ + xt = xT(ctx->opcode); \ + } else { \ + xt = DQxT(ctx->opcode); \ + } \ + \ + if (xt < 32) { \ + if (unlikely(!ctx->vsx_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VSXU); \ + return; \ + } \ + } else { \ + if (unlikely(!ctx->altivec_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VPU); \ + return; \ + } \ + } \ + xth = tcg_temp_new_i64(); \ + xtl = tcg_temp_new_i64(); \ + get_cpu_vsrh(xth, xt); \ + get_cpu_vsrl(xtl, xt); \ + gen_set_access_type(ctx, ACCESS_INT); \ + EA = tcg_temp_new(); \ + if (indexed) { \ + gen_addr_reg_index(ctx, EA); \ + } else { \ + gen_addr_imm_index(ctx, EA, 0x0F); \ + } \ + if (ctx->le_mode) { \ + tcg_gen_qemu_##op(xtl, EA, ctx->mem_idx, MO_LEQ); \ + tcg_gen_addi_tl(EA, EA, 8); \ + tcg_gen_qemu_##op(xth, EA, ctx->mem_idx, MO_LEQ); \ + } else { \ + tcg_gen_qemu_##op(xth, EA, ctx->mem_idx, MO_BEQ); \ + tcg_gen_addi_tl(EA, EA, 8); \ + tcg_gen_qemu_##op(xtl, EA, ctx->mem_idx, MO_BEQ); \ + } \ + tcg_temp_free(EA); \ + tcg_temp_free_i64(xth); \ + tcg_temp_free_i64(xtl); \ +} + +VSX_VECTOR_STORE(stxv, st_i64, 0) +VSX_VECTOR_STORE(stxvx, st_i64, 1) #ifdef TARGET_PPC64 #define VSX_VECTOR_LOAD_STORE_LENGTH(name) \ @@ -329,7 +378,6 @@ static void gen_##name(DisasContext *ctx) \ return; \ } \ xth = tcg_temp_new_i64(); \ - get_cpu_vsrh(xth, rD(ctx->opcode) + 32); \ gen_set_access_type(ctx, ACCESS_INT); \ EA = tcg_temp_new(); \ gen_addr_imm_index(ctx, EA, 0x03); \ @@ -513,8 +561,8 @@ static void gen_##name(DisasContext *ctx) \ tcg_temp_free_i64(xth); \ } -VSX_LOAD_SCALAR_DS(stxsd, st64_i64) -VSX_LOAD_SCALAR_DS(stxssp, st32fs) +VSX_STORE_SCALAR_DS(stxsd, st64_i64) +VSX_STORE_SCALAR_DS(stxssp, st32fs) static void gen_mfvsrwz(DisasContext *ctx) { @@ -858,8 +906,8 @@ static void glue(gen_, name)(DisasContext *ctx) \ xbh = tcg_temp_new_i64(); \ xbl = tcg_temp_new_i64(); \ sgm = tcg_temp_new_i64(); \ - set_cpu_vsrh(xB(ctx->opcode), xbh); \ - set_cpu_vsrl(xB(ctx->opcode), xbl); \ + get_cpu_vsrh(xbh, xB(ctx->opcode)); \ + get_cpu_vsrl(xbl, xB(ctx->opcode)); \ tcg_gen_movi_i64(sgm, sgn_mask); \ switch (op) { \ case OP_ABS: { \ @@ -1192,7 +1240,7 @@ static void gen_xxbrq(DisasContext *ctx) tcg_gen_bswap64_i64(xtl, xbh); set_cpu_vsrl(xT(ctx->opcode), xtl); tcg_gen_mov_i64(xth, t0); - set_cpu_vsrl(xT(ctx->opcode), xth); + set_cpu_vsrh(xT(ctx->opcode), xth); tcg_temp_free_i64(t0); tcg_temp_free_i64(xth); @@ -1220,7 +1268,7 @@ static void gen_xxbrw(DisasContext *ctx) get_cpu_vsrl(xbl, xB(ctx->opcode)); gen_bswap32x4(xth, xtl, xbh, xbl); - set_cpu_vsrl(xT(ctx->opcode), xth); + set_cpu_vsrh(xT(ctx->opcode), xth); set_cpu_vsrl(xT(ctx->opcode), xtl); tcg_temp_free_i64(xth); @@ -1355,13 +1403,13 @@ static void gen_xxspltib(DisasContext *ctx) int rt = xT(ctx->opcode); if (rt < 32) { - if (unlikely(!ctx->altivec_enabled)) { - gen_exception(ctx, POWERPC_EXCP_VPU); + if (unlikely(!ctx->vsx_enabled)) { + gen_exception(ctx, POWERPC_EXCP_VSXU); return; } } else { - if (unlikely(!ctx->vsx_enabled)) { - gen_exception(ctx, POWERPC_EXCP_VSXU); + if (unlikely(!ctx->altivec_enabled)) { + gen_exception(ctx, POWERPC_EXCP_VPU); return; } } @@ -1820,7 +1868,7 @@ static void gen_xvxsigdp(DisasContext *ctx) tcg_gen_movi_i64(t0, 0x0010000000000000); tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0); tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0); - tcg_gen_deposit_i64(xth, t0, xbl, 0, 52); + tcg_gen_deposit_i64(xtl, t0, xbl, 0, 52); set_cpu_vsrl(xT(ctx->opcode), xtl); tcg_temp_free_i64(t0); |