aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/i386/cpu.c3
-rw-r--r--target/i386/cpu.h1
-rw-r--r--target/mips/dsp_helper.c40
-rw-r--r--target/mips/lmi_helper.c8
-rw-r--r--target/mips/msa_helper.c542
-rw-r--r--target/mips/translate.c152
-rw-r--r--target/ppc/helper.h12
-rw-r--r--target/ppc/int_helper.c53
-rw-r--r--target/ppc/kvm.c9
-rw-r--r--target/ppc/kvm_ppc.h6
-rw-r--r--target/ppc/trace-events2
-rw-r--r--target/ppc/translate/vmx-impl.inc.c24
-rw-r--r--target/ppc/translate/vsx-impl.inc.c86
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);