[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 17/20] target-mips: add MSA 2RF format instructions
From: |
Yongbok Kim |
Subject: |
[Qemu-devel] [PATCH 17/20] target-mips: add MSA 2RF format instructions |
Date: |
Mon, 14 Jul 2014 10:56:00 +0100 |
add MSA 2RF format instructions
Signed-off-by: Yongbok Kim <address@hidden>
---
target-mips/helper.h | 16 ++
target-mips/msa_helper.c | 656 ++++++++++++++++++++++++++++++++++++++++++++++
target-mips/translate.c | 76 ++++++
3 files changed, 748 insertions(+), 0 deletions(-)
diff --git a/target-mips/helper.h b/target-mips/helper.h
index b87bb50..c86bd36 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -747,6 +747,7 @@ DEF_HELPER_5(msa_dpsub_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fadd_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcaf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fceq_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32)
DEF_HELPER_5(msa_fcle_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fclt_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcne_df, void, env, i32, i32, i32, i32)
@@ -759,7 +760,14 @@ DEF_HELPER_5(msa_fcune_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fdiv_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fexdo_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fexp2_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_fexupl_df, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_fexupr_df, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_ffint_s_df, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_ffql_df, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_ffqr_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_flog2_df, void, env, i32, i32, i32)
DEF_HELPER_5(msa_fmadd_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmax_a_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmax_df, void, env, i32, i32, i32, i32)
@@ -767,19 +775,27 @@ DEF_HELPER_5(msa_fmin_a_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmin_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmsub_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmul_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_frcp_df, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_frint_df, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_frsqrt_df, void, env, i32, i32, i32)
DEF_HELPER_5(msa_fsaf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fseq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsle_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fslt_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsor_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_fsqrt_df, void, env, i32, i32, i32)
DEF_HELPER_5(msa_fsub_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsueq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsule_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsult_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsun_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsune_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_ftint_s_df, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_ftint_u_df, void, env, i32, i32, i32)
DEF_HELPER_5(msa_ftq_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32)
DEF_HELPER_5(msa_hadd_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_hadd_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_hsub_s_df, void, env, i32, i32, i32, i32)
diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c
index aa165ac..d152953 100644
--- a/target-mips/msa_helper.c
+++ b/target-mips/msa_helper.c
@@ -3240,6 +3240,9 @@ void helper_msa_msubr_q_df(CPUMIPSState *env, uint32_t
df, uint32_t wd,
}
}
+#define FLOAT_ONE32 make_float32(0x3f8 << 20)
+#define FLOAT_ONE64 make_float64(0x3ffULL << 52)
+
#define FLOAT_SNAN16 (float16_default_nan ^ 0x0220)
/* 0x7c20 */
#define FLOAT_SNAN32 (float32_default_nan ^ 0x00400020)
@@ -3352,6 +3355,28 @@ static inline int update_msacsr(CPUMIPSState *env, int
action, int denormal)
(!float ## BITS ## _is_zero(ARG) \
&& float ## BITS ## _is_zero_or_denormal(ARG))
+#define MSA_FLOAT_UNOP0(DEST, OP, ARG, BITS) \
+ do { \
+ int c; \
+ int cause; \
+ int enable; \
+ \
+ set_float_exception_flags(0, &env->active_msa.fp_status); \
+ DEST = float ## BITS ## _ ## OP(ARG, &env->active_msa.fp_status); \
+ c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0); \
+ enable = GET_FP_ENABLE(env->active_msa.msacsr) | FP_UNIMPLEMENTED; \
+ cause = c & enable; \
+ \
+ if (cause) { \
+ DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \
+ } \
+ else { \
+ if (float ## BITS ## _is_any_nan(ARG)) { \
+ DEST = 0; \
+ } \
+ } \
+ } while (0)
+
#define MSA_FLOAT_UNOP_XD(DEST, OP, ARG, BITS, XBITS) \
do { \
int c; \
@@ -3386,6 +3411,37 @@ static inline int update_msacsr(CPUMIPSState *env, int
action, int denormal)
} \
} while (0)
+#define MSA_FLOAT_LOGB(DEST, ARG, BITS) \
+ do { \
+ int c; \
+ int cause; \
+ int enable; \
+ \
+ set_float_exception_flags(0, &env->active_msa.fp_status); \
+ set_float_rounding_mode(float_round_down, \
+ &env->active_msa.fp_status); \
+ DEST = float ## BITS ## _ ## log2(ARG, \
+ &env->active_msa.fp_status); \
+ DEST = float ## BITS ## _ ## round_to_int(DEST, \
+ &env->active_msa.fp_status); \
+ set_float_rounding_mode(ieee_rm[(env->active_msa.msacsr & \
+ MSACSR_RM_MASK) >> MSACSR_RM_POS], \
+ &env->active_msa.fp_status); \
+ \
+ set_float_exception_flags( \
+ get_float_exception_flags(&env->active_msa.fp_status) \
+ & (~float_flag_inexact), \
+ &env->active_msa.fp_status); \
+ \
+ c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
+ enable = GET_FP_ENABLE(env->active_msa.msacsr) | FP_UNIMPLEMENTED; \
+ cause = c & enable; \
+ \
+ if (cause) { \
+ DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \
+ } \
+ } while (0)
+
#define MSA_FLOAT_BINOP(DEST, OP, ARG1, ARG2, BITS) \
do { \
int c; \
@@ -3422,6 +3478,27 @@ static inline int update_msacsr(CPUMIPSState *env, int
action, int denormal)
} \
} while (0)
+#define MSA_FLOAT_RECIPROCAL(DEST, ARG, BITS) \
+ do { \
+ int c; \
+ int cause; \
+ int enable; \
+ \
+ set_float_exception_flags(0, &env->active_msa.fp_status); \
+ DEST = float ## BITS ## _ ## div(FLOAT_ONE ## BITS, ARG, \
+ &env->active_msa.fp_status); \
+ c = update_msacsr(env, float ## BITS ## _is_infinity(ARG) || \
+ float ## BITS ## _is_quiet_nan(DEST) ? \
+ 0 : RECIPROCAL_INEXACT, \
+ IS_DENORMAL(DEST, BITS)); \
+ enable = GET_FP_ENABLE(env->active_msa.msacsr) | FP_UNIMPLEMENTED; \
+ cause = c & enable; \
+ \
+ if (cause) { \
+ DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \
+ } \
+ } while (0)
+
#define MSA_FLOAT_MULADD(DEST, ARG1, ARG2, ARG3, NEGATE, BITS) \
do { \
int c; \
@@ -3566,6 +3643,36 @@ void helper_msa_fdiv_df(CPUMIPSState *env, uint32_t df,
uint32_t wd,
msa_move_v(pwd, pwx);
}
+void helper_msa_fsqrt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ clear_msacsr_cause(env);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(W(pwx, i), sqrt, W(pws, i), 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(D(pwx, i), sqrt, D(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ check_msacsr_cause(env);
+
+ msa_move_v(pwd, pwx);
+}
+
void helper_msa_fexp2_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
uint32_t ws, uint32_t wt)
{
@@ -3603,6 +3710,36 @@ void helper_msa_fexp2_df(CPUMIPSState *env, uint32_t df,
uint32_t wd,
msa_move_v(pwd, pwx);
}
+void helper_msa_flog2_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ clear_msacsr_cause(env);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_LOGB(W(pwx, i), W(pws, i), 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_LOGB(D(pwx, i), D(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ check_msacsr_cause(env);
+
+ msa_move_v(pwd, pwx);
+}
+
void helper_msa_fmadd_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
uint32_t ws, uint32_t wt)
{
@@ -4417,6 +4554,89 @@ void helper_msa_fsor_df(CPUMIPSState *env, uint32_t df,
uint32_t wd,
compare_or(env, pwd, pws, pwt, df, 0);
}
+#define MSA_FLOAT_CLASS_SIGNALING_NAN 0x001
+#define MSA_FLOAT_CLASS_QUIET_NAN 0x002
+
+#define MSA_FLOAT_CLASS_NEGATIVE_INFINITY 0x004
+#define MSA_FLOAT_CLASS_NEGATIVE_NORMAL 0x008
+#define MSA_FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010
+#define MSA_FLOAT_CLASS_NEGATIVE_ZERO 0x020
+
+#define MSA_FLOAT_CLASS_POSITIVE_INFINITY 0x040
+#define MSA_FLOAT_CLASS_POSITIVE_NORMAL 0x080
+#define MSA_FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100
+#define MSA_FLOAT_CLASS_POSITIVE_ZERO 0x200
+
+#define MSA_FLOAT_CLASS(ARG, BITS) \
+ do { \
+ int mask; \
+ int snan, qnan, inf, neg, zero, dnmz; \
+ \
+ snan = float ## BITS ## _is_signaling_nan(ARG); \
+ qnan = float ## BITS ## _is_quiet_nan(ARG); \
+ inf = float ## BITS ## _is_infinity(ARG); \
+ neg = float ## BITS ## _is_neg(ARG); \
+ zero = float ## BITS ## _is_zero(ARG); \
+ dnmz = float ## BITS ## _is_zero_or_denormal(ARG); \
+ \
+ mask = 0; \
+ if (snan) { \
+ mask |= MSA_FLOAT_CLASS_SIGNALING_NAN; \
+ } \
+ else if (qnan) { \
+ mask |= MSA_FLOAT_CLASS_QUIET_NAN; \
+ } else if (neg) { \
+ if (inf) { \
+ mask |= MSA_FLOAT_CLASS_NEGATIVE_INFINITY; \
+ } else if (zero) { \
+ mask |= MSA_FLOAT_CLASS_NEGATIVE_ZERO; \
+ } else if (dnmz) { \
+ mask |= MSA_FLOAT_CLASS_NEGATIVE_SUBNORMAL; \
+ } \
+ else { \
+ mask |= MSA_FLOAT_CLASS_NEGATIVE_NORMAL; \
+ } \
+ } else { \
+ if (inf) { \
+ mask |= MSA_FLOAT_CLASS_POSITIVE_INFINITY; \
+ } else if (zero) { \
+ mask |= MSA_FLOAT_CLASS_POSITIVE_ZERO; \
+ } else if (dnmz) { \
+ mask |= MSA_FLOAT_CLASS_POSITIVE_SUBNORMAL; \
+ } else { \
+ mask |= MSA_FLOAT_CLASS_POSITIVE_NORMAL; \
+ } \
+ } \
+ return mask; \
+ } while (0)
+
+static inline int64_t msa_fclass_df(CPUMIPSState *env, uint32_t df, int64_t
arg)
+{
+ if (df == DF_WORD) {
+ MSA_FLOAT_CLASS(arg, 32);
+ } else {
+ MSA_FLOAT_CLASS(arg, 64);
+ }
+}
+
+void helper_msa_fclass_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ uint64_t td, ts;
+ int i;
+ int df_bits = 8 * (1 << df);
+
+ for (i = 0; i < MSA_WRLEN / df_bits; i++) {
+ ts = msa_load_wr_elem_s64(env, ws, df, i);
+ td = msa_fclass_df(env, df, ts);
+ msa_store_wr_elem(env, td, wd, df, i);
+ }
+
+ if (env->active_msa.msair & MSAIR_WRP_BIT) {
+ env->active_msa.msamodify |= (1 << wd);
+ }
+}
+
static inline float16 float16_from_float32(int32 a, flag ieee STATUS_PARAM)
{
float16 f_val;
@@ -4437,6 +4657,26 @@ static inline float32 float32_from_float64(int64 a
STATUS_PARAM)
return a < 0 ? (f_val | (1 << 31)) : f_val;
}
+static inline float32 float32_from_float16(int16_t a, flag ieee STATUS_PARAM)
+{
+ float32 f_val;
+
+ f_val = float16_to_float32((float16)a, ieee STATUS_VAR);
+ f_val = float32_maybe_silence_nan(f_val);
+
+ return a < 0 ? (f_val | (1 << 31)) : f_val;
+}
+
+static inline float64 float64_from_float32(int32 a STATUS_PARAM)
+{
+ float64 f_val;
+
+ f_val = float32_to_float64((float64)a STATUS_VAR);
+ f_val = float64_maybe_silence_nan(f_val);
+
+ return a < 0 ? (f_val | (1ULL << 63)) : f_val;
+}
+
void helper_msa_fexdo_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
uint32_t ws, uint32_t wt)
{
@@ -4472,6 +4712,308 @@ void helper_msa_fexdo_df(CPUMIPSState *env, uint32_t
df, uint32_t wd,
msa_move_v(pwd, pwx);
}
+void helper_msa_fexupl_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ /* Half precision floats come in two formats: standard
+ IEEE and "ARM" format. The latter gains extra exponent
+ range by omitting the NaN/Inf encodings. */
+ flag ieee = 1;
+
+ MSA_FLOAT_BINOP(W(pwx, i), from_float16, HL(pws, i), ieee, 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(D(pwx, i), from_float32, WL(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ check_msacsr_cause(env);
+ msa_move_v(pwd, pwx);
+}
+
+void helper_msa_fexupr_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ /* Half precision floats come in two formats: standard
+ IEEE and "ARM" format. The latter gains extra exponent
+ range by omitting the NaN/Inf encodings. */
+ flag ieee = 1;
+
+ MSA_FLOAT_BINOP(W(pwx, i), from_float16, HR(pws, i), ieee, 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(D(pwx, i), from_float32, WR(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ check_msacsr_cause(env);
+ msa_move_v(pwd, pwx);
+}
+
+#define float32_from_int32 int32_to_float32
+#define float32_from_uint32 uint32_to_float32
+
+#define float64_from_int64 int64_to_float64
+#define float64_from_uint64 uint64_to_float64
+
+void helper_msa_ffint_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ clear_msacsr_cause(env);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(W(pwx, i), from_int32, W(pws, i), 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(D(pwx, i), from_int64, D(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ check_msacsr_cause(env);
+
+ msa_move_v(pwd, pwx);
+}
+
+void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ clear_msacsr_cause(env);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(W(pwx, i), from_uint32, W(pws, i), 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(D(pwx, i), from_uint64, D(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ check_msacsr_cause(env);
+
+ msa_move_v(pwd, pwx);
+}
+
+void helper_msa_ftint_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ clear_msacsr_cause(env);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP0(W(pwx, i), to_int32, W(pws, i), 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP0(D(pwx, i), to_int64, D(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ check_msacsr_cause(env);
+
+ msa_move_v(pwd, pwx);
+}
+
+void helper_msa_ftint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ clear_msacsr_cause(env);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP0(W(pwx, i), to_uint32, W(pws, i), 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP0(D(pwx, i), to_uint64, D(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ check_msacsr_cause(env);
+
+ msa_move_v(pwd, pwx);
+}
+
+void helper_msa_ftrunc_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ clear_msacsr_cause(env);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP0(W(pwx, i), to_int32_round_to_zero, W(pws, i), 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP0(D(pwx, i), to_int64_round_to_zero, D(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ check_msacsr_cause(env);
+
+ msa_move_v(pwd, pwx);
+}
+
+void helper_msa_ftrunc_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ clear_msacsr_cause(env);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP0(W(pwx, i), to_uint32_round_to_zero, W(pws, i), 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP0(D(pwx, i), to_uint64_round_to_zero, D(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ check_msacsr_cause(env);
+
+ msa_move_v(pwd, pwx);
+}
+
+void helper_msa_frint_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ clear_msacsr_cause(env);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(W(pwx, i), round_to_int, W(pws, i), 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(D(pwx, i), round_to_int, D(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ check_msacsr_cause(env);
+
+ msa_move_v(pwd, pwx);
+}
+
+static inline float32 float32_from_q16(int16_t a STATUS_PARAM)
+{
+ float32 f_val;
+
+ /* conversion as integer and scaling */
+ f_val = int32_to_float32(a STATUS_VAR);
+ f_val = float32_scalbn(f_val, -15 STATUS_VAR);
+
+ return f_val;
+}
+
+static inline float64 float64_from_q32(int32 a STATUS_PARAM)
+{
+ float64 f_val;
+
+ /* conversion as integer and scaling */
+ f_val = int32_to_float64(a STATUS_VAR);
+ f_val = float64_scalbn(f_val, -31 STATUS_VAR);
+
+ return f_val;
+}
+
static inline int16_t float32_to_q16(float32 a STATUS_PARAM)
{
int32 q_val;
@@ -4576,6 +5118,58 @@ static inline int32 float64_to_q32(float64 a
STATUS_PARAM)
return (int32)q_val;
}
+void helper_msa_ffql_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(W(pwx, i), from_q16, HL(pws, i), 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(D(pwx, i), from_q32, WL(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ msa_move_v(pwd, pwx);
+}
+
+void helper_msa_ffqr_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(W(pwx, i), from_q16, HR(pws, i), 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_UNOP(D(pwx, i), from_q32, WR(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ msa_move_v(pwd, pwx);
+}
+
void helper_msa_ftq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
uint32_t ws, uint32_t wt)
{
@@ -4608,6 +5202,68 @@ void helper_msa_ftq_df(CPUMIPSState *env, uint32_t df,
uint32_t wd,
msa_move_v(pwd, pwx);
}
+void helper_msa_frcp_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ clear_msacsr_cause(env);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_RECIPROCAL(W(pwx, i), W(pws, i), 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_RECIPROCAL(D(pwx, i), D(pws, i), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ check_msacsr_cause(env);
+
+ msa_move_v(pwd, pwx);
+}
+
+void helper_msa_frsqrt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t ws)
+{
+ wr_t wx, *pwx = &wx;
+ void *pwd = &(env->active_fpu.fpr[wd]);
+ void *pws = &(env->active_fpu.fpr[ws]);
+
+ clear_msacsr_cause(env);
+
+ switch (df) {
+ case DF_WORD:
+ ALL_W_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_RECIPROCAL(W(pwx, i), float32_sqrt(W(pws, i),
+ &env->active_msa.fp_status), 32);
+ } DONE_ALL_ELEMENTS;
+ break;
+ case DF_DOUBLE:
+ ALL_D_ELEMENTS(i, MSA_WRLEN) {
+ MSA_FLOAT_RECIPROCAL(D(pwx, i), float64_sqrt(D(pws, i),
+ &env->active_msa.fp_status), 64);
+ } DONE_ALL_ELEMENTS;
+ break;
+ default:
+ /* shouldn't get here */
+ assert(0);
+ }
+
+ check_msacsr_cause(env);
+
+ msa_move_v(pwd, pwx);
+}
+
target_ulong helper_msa_cfcmsa(CPUMIPSState *env, uint32_t cs)
{
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 4185019..dcfe830 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15737,6 +15737,82 @@ static void gen_msa_vec(CPUMIPSState *env,
DisasContext *ctx)
}
break;
case OPC_MSA_2RF:
+ {
+ uint8_t df = (ctx->opcode >> 16) & 0x1 /* df [16:16] */;
+ /* adjust df value for floating-point instruction */
+ df = df + 2;
+ TCGv_i32 tdf = tcg_const_i32(df);
+
+ switch (MASK_MSA_2RF(opcode)) {
+ case OPC_MSA_FCLASS_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FTRUNC_S_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FTRUNC_U_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FSQRT_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FRSQRT_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FRCP_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FRINT_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FRLOG2_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FEXUPL_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FEXUPR_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FFQL_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FFQR_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FINT_S_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FINT_U_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FFINT_S_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_MSA_FFINT_U_df:
+ check_msa_access(env, ctx, -1, ws, wd);
+ gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
+ break;
+ }
+
+ tcg_temp_free_i32(tdf);
+ }
+ break;
default:
break;
}
--
1.7.4
- [Qemu-devel] [PATCH 10/20] target-mips: add MSA I8 format instructions, (continued)
- [Qemu-devel] [PATCH 10/20] target-mips: add MSA I8 format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 11/20] target-mips: add MSA I5 format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 12/20] target-mips: add MSA BIT format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 14/20] target-mips: add MSA ELM format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 16/20] target-mips: add MSA VEC/2R format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 18/20] target-mips: add MSA MI10 format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 15/20] target-mips: add MSA 3RF format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 20/20] target-mips: add MSA support to mips32r5-generic, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 13/20] target-mips: add MSA 3R format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 19/20] disas/mips.c: disassemble MSA instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 17/20] target-mips: add MSA 2RF format instructions,
Yongbok Kim <=