From patchwork Mon Nov 3 16:11:45 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Alrae X-Patchwork-Id: 406295 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id EE95014007F for ; Tue, 4 Nov 2014 03:35:40 +1100 (AEDT) Received: from localhost ([::1]:35915 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XlKbS-0004RE-Th for incoming@patchwork.ozlabs.org; Mon, 03 Nov 2014 11:35:38 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46549) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XlKFQ-0004qu-U1 for qemu-devel@nongnu.org; Mon, 03 Nov 2014 11:12:58 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XlKFL-0005eY-P9 for qemu-devel@nongnu.org; Mon, 03 Nov 2014 11:12:52 -0500 Received: from mailapp01.imgtec.com ([195.59.15.196]:33588) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XlKFL-0005eJ-E7 for qemu-devel@nongnu.org; Mon, 03 Nov 2014 11:12:47 -0500 Received: from KLMAIL01.kl.imgtec.org (unknown [192.168.5.35]) by Websense Email Security Gateway with ESMTPS id 0F73FF543174F for ; Mon, 3 Nov 2014 16:12:43 +0000 (GMT) Received: from virtUbuntuLTP.kl.imgtec.org (192.168.14.163) by KLMAIL01.kl.imgtec.org (192.168.5.35) with Microsoft SMTP Server (TLS) id 14.3.195.1; Mon, 3 Nov 2014 16:12:45 +0000 From: Leon Alrae To: Date: Mon, 3 Nov 2014 16:11:45 +0000 Message-ID: <1415031108-15039-32-git-send-email-leon.alrae@imgtec.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1415031108-15039-1-git-send-email-leon.alrae@imgtec.com> References: <1415031108-15039-1-git-send-email-leon.alrae@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.14.163] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.59.15.196 Cc: Yongbok Kim Subject: [Qemu-devel] [PULL 31/34] target-mips: add MSA 2RF format instructions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Yongbok Kim add MSA 2RF format instructions Signed-off-by: Yongbok Kim Signed-off-by: Leon Alrae --- target-mips/helper.h | 17 ++ target-mips/msa_helper.c | 530 +++++++++++++++++++++++++++++++++++++++++++++++ target-mips/translate.c | 74 +++++++ 3 files changed, 621 insertions(+) diff --git a/target-mips/helper.h b/target-mips/helper.h index 3185c1d..cb8b40e 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -912,3 +912,20 @@ DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_pcnt_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_fclass_df, void, env, 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_4(msa_fsqrt_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_frsqrt_df, void, env, 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_flog2_df, void, env, 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_ffql_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffqr_df, void, env, 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_4(msa_ffint_s_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index a96a648..b08f37f 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -1498,6 +1498,7 @@ void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \ MSA_UNOP_DF(nlzc) MSA_UNOP_DF(nloc) MSA_UNOP_DF(pcnt) +#undef MSA_UNOP_DF #define FLOAT_ONE32 make_float32(0x3f8 << 20) #define FLOAT_ONE64 make_float64(0x3ffULL << 52) @@ -2904,3 +2905,532 @@ void helper_msa_fmax_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd, msa_move_v(pwd, pwx); } + +void helper_msa_fclass_df(CPUMIPSState *env, uint32_t df, + uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + if (df == DF_WORD) { + pwd->w[0] = helper_float_class_s(pws->w[0]); + pwd->w[1] = helper_float_class_s(pws->w[1]); + pwd->w[2] = helper_float_class_s(pws->w[2]); + pwd->w[3] = helper_float_class_s(pws->w[3]); + } else { + pwd->d[0] = helper_float_class_d(pws->d[0]); + pwd->d[1] = helper_float_class_d(pws->d[1]); + } +} + +#define MSA_FLOAT_UNOP0(DEST, OP, ARG, BITS) \ + do { \ + int c; \ + \ + set_float_exception_flags(0, &env->active_tc.msa_fp_status); \ + DEST = float ## BITS ## _ ## OP(ARG, &env->active_tc.msa_fp_status);\ + c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0); \ + \ + if (get_enabled_exceptions(env, c)) { \ + DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \ + } else if (float ## BITS ## _is_any_nan(ARG)) { \ + DEST = 0; \ + } \ + } while (0) + +void helper_msa_ftrunc_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws) +{ + wr_t wx, *pwx = &wx; + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + uint32_t i; + + clear_msacsr_cause(env); + + switch (df) { + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + MSA_FLOAT_UNOP0(pwx->w[i], to_int32_round_to_zero, pws->w[i], 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_UNOP0(pwx->d[i], to_int64_round_to_zero, pws->d[i], 64); + } + break; + default: + 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; + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + uint32_t i; + + clear_msacsr_cause(env); + + switch (df) { + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + MSA_FLOAT_UNOP0(pwx->w[i], to_uint32_round_to_zero, pws->w[i], 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_UNOP0(pwx->d[i], to_uint64_round_to_zero, pws->d[i], 64); + } + break; + default: + assert(0); + } + + check_msacsr_cause(env); + + 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; + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + uint32_t i; + + clear_msacsr_cause(env); + + switch (df) { + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + MSA_FLOAT_UNOP(pwx->w[i], sqrt, pws->w[i], 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_UNOP(pwx->d[i], sqrt, pws->d[i], 64); + } + break; + default: + assert(0); + } + + check_msacsr_cause(env); + + msa_move_v(pwd, pwx); +} + +#define MSA_FLOAT_RECIPROCAL(DEST, ARG, BITS) \ + do { \ + int c; \ + \ + set_float_exception_flags(0, &env->active_tc.msa_fp_status); \ + DEST = float ## BITS ## _ ## div(FLOAT_ONE ## BITS, ARG, \ + &env->active_tc.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)); \ + \ + if (get_enabled_exceptions(env, c)) { \ + DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \ + } \ + } while (0) + +void helper_msa_frsqrt_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws) +{ + wr_t wx, *pwx = &wx; + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + uint32_t i; + + clear_msacsr_cause(env); + + switch (df) { + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + MSA_FLOAT_RECIPROCAL(pwx->w[i], float32_sqrt(pws->w[i], + &env->active_tc.msa_fp_status), 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_RECIPROCAL(pwx->d[i], float64_sqrt(pws->d[i], + &env->active_tc.msa_fp_status), 64); + } + break; + default: + assert(0); + } + + check_msacsr_cause(env); + + 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; + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + uint32_t i; + + clear_msacsr_cause(env); + + switch (df) { + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + MSA_FLOAT_RECIPROCAL(pwx->w[i], pws->w[i], 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_RECIPROCAL(pwx->d[i], pws->d[i], 64); + } + break; + default: + 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; + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + uint32_t i; + + clear_msacsr_cause(env); + + switch (df) { + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + MSA_FLOAT_UNOP(pwx->w[i], round_to_int, pws->w[i], 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_UNOP(pwx->d[i], round_to_int, pws->d[i], 64); + } + break; + default: + assert(0); + } + + check_msacsr_cause(env); + + msa_move_v(pwd, pwx); +} + +#define MSA_FLOAT_LOGB(DEST, ARG, BITS) \ + do { \ + int c; \ + \ + set_float_exception_flags(0, &env->active_tc.msa_fp_status); \ + set_float_rounding_mode(float_round_down, \ + &env->active_tc.msa_fp_status); \ + DEST = float ## BITS ## _ ## log2(ARG, \ + &env->active_tc.msa_fp_status); \ + DEST = float ## BITS ## _ ## round_to_int(DEST, \ + &env->active_tc.msa_fp_status); \ + set_float_rounding_mode(ieee_rm[(env->active_tc.msacsr & \ + MSACSR_RM_MASK) >> MSACSR_RM], \ + &env->active_tc.msa_fp_status); \ + \ + set_float_exception_flags( \ + get_float_exception_flags(&env->active_tc.msa_fp_status) \ + & (~float_flag_inexact), \ + &env->active_tc.msa_fp_status); \ + \ + c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \ + \ + if (get_enabled_exceptions(env, c)) { \ + DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \ + } \ + } while (0) + +void helper_msa_flog2_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws) +{ + wr_t wx, *pwx = &wx; + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + uint32_t i; + + clear_msacsr_cause(env); + + switch (df) { + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + MSA_FLOAT_LOGB(pwx->w[i], pws->w[i], 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_LOGB(pwx->d[i], pws->d[i], 64); + } + break; + default: + assert(0); + } + + check_msacsr_cause(env); + + 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; + 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_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + /* 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(pwx->w[i], from_float16, Lh(pws, i), ieee, 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_UNOP(pwx->d[i], from_float32, Lw(pws, i), 64); + } + break; + default: + 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; + 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_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + /* 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(pwx->w[i], from_float16, Rh(pws, i), ieee, 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_UNOP(pwx->d[i], from_float32, Rw(pws, i), 64); + } + break; + default: + assert(0); + } + + check_msacsr_cause(env); + msa_move_v(pwd, pwx); +} + +void helper_msa_ffql_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws) +{ + wr_t wx, *pwx = &wx; + 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_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + MSA_FLOAT_UNOP(pwx->w[i], from_q16, Lh(pws, i), 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_UNOP(pwx->d[i], from_q32, Lw(pws, i), 64); + } + break; + default: + 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; + 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_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + MSA_FLOAT_UNOP(pwx->w[i], from_q16, Rh(pws, i), 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_UNOP(pwx->d[i], from_q32, Rw(pws, i), 64); + } + break; + default: + assert(0); + } + + 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; + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + uint32_t i; + + clear_msacsr_cause(env); + + switch (df) { + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + MSA_FLOAT_UNOP0(pwx->w[i], to_int32, pws->w[i], 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_UNOP0(pwx->d[i], to_int64, pws->d[i], 64); + } + break; + default: + 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; + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + uint32_t i; + + clear_msacsr_cause(env); + + switch (df) { + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + MSA_FLOAT_UNOP0(pwx->w[i], to_uint32, pws->w[i], 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_UNOP0(pwx->d[i], to_uint64, pws->d[i], 64); + } + break; + default: + 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; + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + uint32_t i; + + clear_msacsr_cause(env); + + switch (df) { + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + MSA_FLOAT_UNOP(pwx->w[i], from_int32, pws->w[i], 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_UNOP(pwx->d[i], from_int64, pws->d[i], 64); + } + break; + default: + 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; + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + uint32_t i; + + clear_msacsr_cause(env); + + switch (df) { + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + MSA_FLOAT_UNOP(pwx->w[i], from_uint32, pws->w[i], 32); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + MSA_FLOAT_UNOP(pwx->d[i], from_uint64, pws->d[i], 64); + } + break; + default: + assert(0); + } + + check_msacsr_cause(env); + + msa_move_v(pwd, pwx); +} diff --git a/target-mips/translate.c b/target-mips/translate.c index acaf5a3..73d686e 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -18098,6 +18098,77 @@ static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx) tcg_temp_free_i32(tdf); } +static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \ + (op & (0xf << 17))) + uint8_t wt = (ctx->opcode >> 16) & 0x1f; + uint8_t ws = (ctx->opcode >> 11) & 0x1f; + uint8_t wd = (ctx->opcode >> 6) & 0x1f; + uint8_t df = (ctx->opcode >> 16) & 0x1; + TCGv_i32 twd = tcg_const_i32(wd); + TCGv_i32 tws = tcg_const_i32(ws); + TCGv_i32 twt = tcg_const_i32(wt); + /* adjust df value for floating-point instruction */ + TCGv_i32 tdf = tcg_const_i32(df + 2); + + switch (MASK_MSA_2RF(ctx->opcode)) { + case OPC_FCLASS_df: + gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws); + break; + case OPC_FTRUNC_S_df: + gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws); + break; + case OPC_FTRUNC_U_df: + gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws); + break; + case OPC_FSQRT_df: + gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws); + break; + case OPC_FRSQRT_df: + gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws); + break; + case OPC_FRCP_df: + gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws); + break; + case OPC_FRINT_df: + gen_helper_msa_frint_df(cpu_env, tdf, twd, tws); + break; + case OPC_FLOG2_df: + gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws); + break; + case OPC_FEXUPL_df: + gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws); + break; + case OPC_FEXUPR_df: + gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws); + break; + case OPC_FFQL_df: + gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws); + break; + case OPC_FFQR_df: + gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws); + break; + case OPC_FTINT_S_df: + gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws); + break; + case OPC_FTINT_U_df: + gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws); + break; + case OPC_FFINT_S_df: + gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws); + break; + case OPC_FFINT_U_df: + gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws); + break; + } + + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); + tcg_temp_free_i32(twt); + tcg_temp_free_i32(tdf); +} + static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx) { #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21))) @@ -18156,6 +18227,9 @@ static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx) case OPC_MSA_2R: gen_msa_2r(env, ctx); break; + case OPC_MSA_2RF: + gen_msa_2rf(env, ctx); + break; default: MIPS_INVAL("MSA instruction"); generate_exception(ctx, EXCP_RI);