diff --git a/target/mips/helper.h b/target/mips/helper.h index 51f0e1c183b3a99aed2d5821c0f83e760a55c52a..d615c83c54897fcc28683a26ac9628dbda684720 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -777,6 +777,123 @@ DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env) DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) /* MIPS SIMD Architecture */ + +DEF_HELPER_3(msa_nloc_b, void, env, i32, i32) +DEF_HELPER_3(msa_nloc_h, void, env, i32, i32) +DEF_HELPER_3(msa_nloc_w, void, env, i32, i32) +DEF_HELPER_3(msa_nloc_d, void, env, i32, i32) + +DEF_HELPER_3(msa_nlzc_b, void, env, i32, i32) +DEF_HELPER_3(msa_nlzc_h, void, env, i32, i32) +DEF_HELPER_3(msa_nlzc_w, void, env, i32, i32) +DEF_HELPER_3(msa_nlzc_d, void, env, i32, i32) + +DEF_HELPER_3(msa_pcnt_b, void, env, i32, i32) +DEF_HELPER_3(msa_pcnt_h, void, env, i32, i32) +DEF_HELPER_3(msa_pcnt_w, void, env, i32, i32) +DEF_HELPER_3(msa_pcnt_d, void, env, i32, i32) + +DEF_HELPER_4(msa_binsl_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_binsl_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_binsl_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_binsl_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_binsr_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_binsr_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_binsr_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_binsr_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_bclr_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bclr_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bclr_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bclr_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_bneg_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bneg_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bneg_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bneg_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_bset_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bset_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bset_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bset_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_ave_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ave_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ave_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ave_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_ave_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ave_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ave_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ave_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_aver_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_aver_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_aver_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_aver_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_aver_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_aver_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_aver_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_aver_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_ceq_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ceq_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ceq_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ceq_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_cle_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_cle_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_cle_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_cle_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_cle_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_cle_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_cle_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_cle_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_clt_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_clt_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_clt_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_clt_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_clt_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_clt_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_clt_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_clt_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_div_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_div_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_div_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_div_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_div_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_div_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_div_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_div_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_mod_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mod_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mod_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mod_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_mod_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mod_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mod_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mod_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32) + +DEF_HELPER_3(msa_move_v, void, env, i32, i32) + DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) @@ -815,9 +932,6 @@ DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sll_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sra_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_srl_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_bclr_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_bset_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_bneg_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_addv_df, void, env, i32, i32, i32, i32) @@ -828,19 +942,10 @@ DEF_HELPER_5(msa_min_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_min_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_max_a_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_min_a_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_ceq_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_clt_s_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_clt_u_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_cle_s_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_cle_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_add_a_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_adds_a_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_adds_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_adds_u_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_ave_s_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_ave_u_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_aver_s_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_aver_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_subs_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_subs_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32) @@ -850,10 +955,6 @@ DEF_HELPER_5(msa_asub_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_maddv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_div_s_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_div_u_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_mod_s_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_mod_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_dotp_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_dpadd_s_df, void, env, i32, i32, i32, i32) @@ -882,7 +983,6 @@ DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32) DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32) DEF_HELPER_2(msa_cfcmsa, tl, env, i32) -DEF_HELPER_3(msa_move_v, void, env, i32, i32) DEF_HELPER_5(msa_fcaf_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fcun_df, void, env, i32, i32, i32, i32) @@ -926,17 +1026,7 @@ DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_msubr_q_df, void, env, i32, i32, i32, i32) -DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32) -DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32) -DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32) -DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32) 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_copy_s_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_copy_s_h, void, env, i32, i32, i32) diff --git a/target/mips/internal.h b/target/mips/internal.h index 685e8d67e994eb02ecb55a71cd17d0b7ae0a6f6b..3f435b5e6319995abfb21088b1a430e3bbea44ad 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -1,4 +1,5 @@ -/* mips internal definitions and helpers +/* + * MIPS internal definitions and helpers * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -9,8 +10,10 @@ #include "fpu/softfloat-helpers.h" -/* MMU types, the first four entries have the same layout as the - CP0C0_MT field. */ +/* + * MMU types, the first four entries have the same layout as the + * CP0C0_MT field. + */ enum mips_mmu_types { MMU_TYPE_NONE, MMU_TYPE_R4000, @@ -160,9 +163,11 @@ static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env) !(env->CP0_Status & (1 << CP0St_EXL)) && !(env->CP0_Status & (1 << CP0St_ERL)) && !(env->hflags & MIPS_HFLAG_DM) && - /* Note that the TCStatus IXMT field is initialized to zero, - and only MT capable cores can set it to one. So we don't - need to check for MT capabilities here. */ + /* + * Note that the TCStatus IXMT field is initialized to zero, + * and only MT capable cores can set it to one. So we don't + * need to check for MT capabilities here. + */ !(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT)); } @@ -177,14 +182,18 @@ static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env) status = env->CP0_Status & CP0Ca_IP_mask; if (env->CP0_Config3 & (1 << CP0C3_VEIC)) { - /* A MIPS configured with a vectorizing external interrupt controller - will feed a vector into the Cause pending lines. The core treats - the status lines as a vector level, not as indiviual masks. */ + /* + * A MIPS configured with a vectorizing external interrupt controller + * will feed a vector into the Cause pending lines. The core treats + * the status lines as a vector level, not as indiviual masks. + */ r = pending > status; } else { - /* A MIPS configured with compatibility or VInt (Vectored Interrupts) - treats the pending lines as individual interrupt lines, the status - lines are individual masks. */ + /* + * A MIPS configured with compatibility or VInt (Vectored Interrupts) + * treats the pending lines as individual interrupt lines, the status + * lines are individual masks. + */ r = (pending & status) != 0; } return r; @@ -275,12 +284,14 @@ static inline int mips_vpe_active(CPUMIPSState *env) active = 0; } - /* Now verify that there are active thread contexts in the VPE. - - This assumes the CPU model will internally reschedule threads - if the active one goes to sleep. If there are no threads available - the active one will be in a sleeping state, and we can turn off - the entire VPE. */ + /* + * Now verify that there are active thread contexts in the VPE. + * + * This assumes the CPU model will internally reschedule threads + * if the active one goes to sleep. If there are no threads available + * the active one will be in a sleeping state, and we can turn off + * the entire VPE. + */ if (!(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_A))) { /* TC is not activated. */ active = 0; @@ -326,7 +337,8 @@ static inline void compute_hflags(CPUMIPSState *env) if (!(env->CP0_Status & (1 << CP0St_EXL)) && !(env->CP0_Status & (1 << CP0St_ERL)) && !(env->hflags & MIPS_HFLAG_DM)) { - env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU; + env->hflags |= (env->CP0_Status >> CP0St_KSU) & + MIPS_HFLAG_KSU; } #if defined(TARGET_MIPS64) if ((env->insn_flags & ISA_MIPS3) && @@ -403,10 +415,12 @@ static inline void compute_hflags(CPUMIPSState *env) env->hflags |= MIPS_HFLAG_COP1X; } } else if (env->insn_flags & ISA_MIPS4) { - /* All supported MIPS IV CPUs use the XX (CU3) to enable - and disable the MIPS IV extensions to the MIPS III ISA. - Some other MIPS IV CPUs ignore the bit, so the check here - would be too restrictive for them. */ + /* + * All supported MIPS IV CPUs use the XX (CU3) to enable + * and disable the MIPS IV extensions to the MIPS III ISA. + * Some other MIPS IV CPUs ignore the bit, so the check here + * would be too restrictive for them. + */ if (env->CP0_Status & (1U << CP0St_CU3)) { env->hflags |= MIPS_HFLAG_COP1X; } diff --git a/target/mips/kvm_mips.h b/target/mips/kvm_mips.h index ae957f37f03fd5807ae99e0eb93415aa3b308580..1e4014792ddc3482f3c516433f5d4a56c038bfb6 100644 --- a/target/mips/kvm_mips.h +++ b/target/mips/kvm_mips.h @@ -7,7 +7,7 @@ * * Copyright (C) 2012-2014 Imagination Technologies Ltd. * Authors: Sanjay Lal -*/ + */ #ifndef KVM_MIPS_H #define KVM_MIPS_H diff --git a/target/mips/mips-defs.h b/target/mips/mips-defs.h index bbf056a5481a48559e80f786bac87b6fdff0cf73..a831bb43844eaa16712664a477065d5b63787010 100644 --- a/target/mips/mips-defs.h +++ b/target/mips/mips-defs.h @@ -1,8 +1,11 @@ #ifndef QEMU_MIPS_DEFS_H #define QEMU_MIPS_DEFS_H -/* If we want to use host float regs... */ -//#define USE_HOST_FLOAT_REGS +/* + * If we want to use host float regs... + * + * #define USE_HOST_FLOAT_REGS + */ /* Real pages are variable size... */ #define MIPS_TLB_MAX 128 @@ -57,43 +60,46 @@ #define ASE_MXU 0x0200000000000000ULL /* MIPS CPU defines. */ -#define CPU_MIPS1 (ISA_MIPS1) -#define CPU_MIPS2 (CPU_MIPS1 | ISA_MIPS2) -#define CPU_MIPS3 (CPU_MIPS2 | ISA_MIPS3) -#define CPU_MIPS4 (CPU_MIPS3 | ISA_MIPS4) -#define CPU_VR54XX (CPU_MIPS4 | INSN_VR54XX) -#define CPU_R5900 (CPU_MIPS3 | INSN_R5900) -#define CPU_LOONGSON2E (CPU_MIPS3 | INSN_LOONGSON2E) -#define CPU_LOONGSON2F (CPU_MIPS3 | INSN_LOONGSON2F) +#define CPU_MIPS1 (ISA_MIPS1) +#define CPU_MIPS2 (CPU_MIPS1 | ISA_MIPS2) +#define CPU_MIPS3 (CPU_MIPS2 | ISA_MIPS3) +#define CPU_MIPS4 (CPU_MIPS3 | ISA_MIPS4) +#define CPU_VR54XX (CPU_MIPS4 | INSN_VR54XX) +#define CPU_R5900 (CPU_MIPS3 | INSN_R5900) +#define CPU_LOONGSON2E (CPU_MIPS3 | INSN_LOONGSON2E) +#define CPU_LOONGSON2F (CPU_MIPS3 | INSN_LOONGSON2F) -#define CPU_MIPS5 (CPU_MIPS4 | ISA_MIPS5) +#define CPU_MIPS5 (CPU_MIPS4 | ISA_MIPS5) /* MIPS Technologies "Release 1" */ -#define CPU_MIPS32 (CPU_MIPS2 | ISA_MIPS32) -#define CPU_MIPS64 (CPU_MIPS5 | CPU_MIPS32 | ISA_MIPS64) +#define CPU_MIPS32 (CPU_MIPS2 | ISA_MIPS32) +#define CPU_MIPS64 (CPU_MIPS5 | CPU_MIPS32 | ISA_MIPS64) /* MIPS Technologies "Release 2" */ -#define CPU_MIPS32R2 (CPU_MIPS32 | ISA_MIPS32R2) -#define CPU_MIPS64R2 (CPU_MIPS64 | CPU_MIPS32R2 | ISA_MIPS64R2) +#define CPU_MIPS32R2 (CPU_MIPS32 | ISA_MIPS32R2) +#define CPU_MIPS64R2 (CPU_MIPS64 | CPU_MIPS32R2 | ISA_MIPS64R2) /* MIPS Technologies "Release 3" */ -#define CPU_MIPS32R3 (CPU_MIPS32R2 | ISA_MIPS32R3) -#define CPU_MIPS64R3 (CPU_MIPS64R2 | CPU_MIPS32R3 | ISA_MIPS64R3) +#define CPU_MIPS32R3 (CPU_MIPS32R2 | ISA_MIPS32R3) +#define CPU_MIPS64R3 (CPU_MIPS64R2 | CPU_MIPS32R3 | ISA_MIPS64R3) /* MIPS Technologies "Release 5" */ -#define CPU_MIPS32R5 (CPU_MIPS32R3 | ISA_MIPS32R5) -#define CPU_MIPS64R5 (CPU_MIPS64R3 | CPU_MIPS32R5 | ISA_MIPS64R5) +#define CPU_MIPS32R5 (CPU_MIPS32R3 | ISA_MIPS32R5) +#define CPU_MIPS64R5 (CPU_MIPS64R3 | CPU_MIPS32R5 | ISA_MIPS64R5) /* MIPS Technologies "Release 6" */ -#define CPU_MIPS32R6 (CPU_MIPS32R5 | ISA_MIPS32R6) -#define CPU_MIPS64R6 (CPU_MIPS64R5 | CPU_MIPS32R6 | ISA_MIPS64R6) +#define CPU_MIPS32R6 (CPU_MIPS32R5 | ISA_MIPS32R6) +#define CPU_MIPS64R6 (CPU_MIPS64R5 | CPU_MIPS32R6 | ISA_MIPS64R6) /* Wave Computing: "nanoMIPS" */ -#define CPU_NANOMIPS32 (CPU_MIPS32R6 | ISA_NANOMIPS32) +#define CPU_NANOMIPS32 (CPU_MIPS32R6 | ISA_NANOMIPS32) -/* Strictly follow the architecture standard: - - Disallow "special" instruction handling for PMON/SPIM. - Note that we still maintain Count/Compare to match the host clock. */ -//#define MIPS_STRICT_STANDARD 1 +/* + * Strictly follow the architecture standard: + * - Disallow "special" instruction handling for PMON/SPIM. + * Note that we still maintain Count/Compare to match the host clock. + * + * #define MIPS_STRICT_STANDARD 1 + */ #endif /* QEMU_MIPS_DEFS_H */ diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index f24061e2af747bbfd752b38a52a6b9fb936c1b7b..a2052baa57c164d6c17faa795f40793fe6302b31 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -65,7 +65,221 @@ * +---------------+----------------------------------------------------------+ */ -/* TODO: insert Bit Count group helpers here */ +static inline int64_t msa_nlzc_df(uint32_t df, int64_t arg) +{ + uint64_t x, y; + int n, c; + + x = UNSIGNED(arg, df); + n = DF_BITS(df); + c = DF_BITS(df) / 2; + + do { + y = x >> c; + if (y != 0) { + n = n - c; + x = y; + } + c = c >> 1; + } while (c != 0); + + return n - x; +} + +static inline int64_t msa_nloc_df(uint32_t df, int64_t arg) +{ + return msa_nlzc_df(df, UNSIGNED((~arg), df)); +} + +void helper_msa_nloc_b(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + pwd->b[0] = msa_nloc_df(DF_BYTE, pws->b[0]); + pwd->b[1] = msa_nloc_df(DF_BYTE, pws->b[1]); + pwd->b[2] = msa_nloc_df(DF_BYTE, pws->b[2]); + pwd->b[3] = msa_nloc_df(DF_BYTE, pws->b[3]); + pwd->b[4] = msa_nloc_df(DF_BYTE, pws->b[4]); + pwd->b[5] = msa_nloc_df(DF_BYTE, pws->b[5]); + pwd->b[6] = msa_nloc_df(DF_BYTE, pws->b[6]); + pwd->b[7] = msa_nloc_df(DF_BYTE, pws->b[7]); + pwd->b[8] = msa_nloc_df(DF_BYTE, pws->b[8]); + pwd->b[9] = msa_nloc_df(DF_BYTE, pws->b[9]); + pwd->b[10] = msa_nloc_df(DF_BYTE, pws->b[10]); + pwd->b[11] = msa_nloc_df(DF_BYTE, pws->b[11]); + pwd->b[12] = msa_nloc_df(DF_BYTE, pws->b[12]); + pwd->b[13] = msa_nloc_df(DF_BYTE, pws->b[13]); + pwd->b[14] = msa_nloc_df(DF_BYTE, pws->b[14]); + pwd->b[15] = msa_nloc_df(DF_BYTE, pws->b[15]); +} + +void helper_msa_nloc_h(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + pwd->h[0] = msa_nloc_df(DF_HALF, pws->h[0]); + pwd->h[1] = msa_nloc_df(DF_HALF, pws->h[1]); + pwd->h[2] = msa_nloc_df(DF_HALF, pws->h[2]); + pwd->h[3] = msa_nloc_df(DF_HALF, pws->h[3]); + pwd->h[4] = msa_nloc_df(DF_HALF, pws->h[4]); + pwd->h[5] = msa_nloc_df(DF_HALF, pws->h[5]); + pwd->h[6] = msa_nloc_df(DF_HALF, pws->h[6]); + pwd->h[7] = msa_nloc_df(DF_HALF, pws->h[7]); +} + +void helper_msa_nloc_w(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + pwd->w[0] = msa_nloc_df(DF_WORD, pws->w[0]); + pwd->w[1] = msa_nloc_df(DF_WORD, pws->w[1]); + pwd->w[2] = msa_nloc_df(DF_WORD, pws->w[2]); + pwd->w[3] = msa_nloc_df(DF_WORD, pws->w[3]); +} + +void helper_msa_nloc_d(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + pwd->d[0] = msa_nloc_df(DF_DOUBLE, pws->d[0]); + pwd->d[1] = msa_nloc_df(DF_DOUBLE, pws->d[1]); +} + +void helper_msa_nlzc_b(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + pwd->b[0] = msa_nlzc_df(DF_BYTE, pws->b[0]); + pwd->b[1] = msa_nlzc_df(DF_BYTE, pws->b[1]); + pwd->b[2] = msa_nlzc_df(DF_BYTE, pws->b[2]); + pwd->b[3] = msa_nlzc_df(DF_BYTE, pws->b[3]); + pwd->b[4] = msa_nlzc_df(DF_BYTE, pws->b[4]); + pwd->b[5] = msa_nlzc_df(DF_BYTE, pws->b[5]); + pwd->b[6] = msa_nlzc_df(DF_BYTE, pws->b[6]); + pwd->b[7] = msa_nlzc_df(DF_BYTE, pws->b[7]); + pwd->b[8] = msa_nlzc_df(DF_BYTE, pws->b[8]); + pwd->b[9] = msa_nlzc_df(DF_BYTE, pws->b[9]); + pwd->b[10] = msa_nlzc_df(DF_BYTE, pws->b[10]); + pwd->b[11] = msa_nlzc_df(DF_BYTE, pws->b[11]); + pwd->b[12] = msa_nlzc_df(DF_BYTE, pws->b[12]); + pwd->b[13] = msa_nlzc_df(DF_BYTE, pws->b[13]); + pwd->b[14] = msa_nlzc_df(DF_BYTE, pws->b[14]); + pwd->b[15] = msa_nlzc_df(DF_BYTE, pws->b[15]); +} + +void helper_msa_nlzc_h(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + pwd->h[0] = msa_nlzc_df(DF_HALF, pws->h[0]); + pwd->h[1] = msa_nlzc_df(DF_HALF, pws->h[1]); + pwd->h[2] = msa_nlzc_df(DF_HALF, pws->h[2]); + pwd->h[3] = msa_nlzc_df(DF_HALF, pws->h[3]); + pwd->h[4] = msa_nlzc_df(DF_HALF, pws->h[4]); + pwd->h[5] = msa_nlzc_df(DF_HALF, pws->h[5]); + pwd->h[6] = msa_nlzc_df(DF_HALF, pws->h[6]); + pwd->h[7] = msa_nlzc_df(DF_HALF, pws->h[7]); +} + +void helper_msa_nlzc_w(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + pwd->w[0] = msa_nlzc_df(DF_WORD, pws->w[0]); + pwd->w[1] = msa_nlzc_df(DF_WORD, pws->w[1]); + pwd->w[2] = msa_nlzc_df(DF_WORD, pws->w[2]); + pwd->w[3] = msa_nlzc_df(DF_WORD, pws->w[3]); +} + +void helper_msa_nlzc_d(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + pwd->d[0] = msa_nlzc_df(DF_DOUBLE, pws->d[0]); + pwd->d[1] = msa_nlzc_df(DF_DOUBLE, pws->d[1]); +} + +static inline int64_t msa_pcnt_df(uint32_t df, int64_t arg) +{ + uint64_t x; + + x = UNSIGNED(arg, df); + + x = (x & 0x5555555555555555ULL) + ((x >> 1) & 0x5555555555555555ULL); + x = (x & 0x3333333333333333ULL) + ((x >> 2) & 0x3333333333333333ULL); + x = (x & 0x0F0F0F0F0F0F0F0FULL) + ((x >> 4) & 0x0F0F0F0F0F0F0F0FULL); + x = (x & 0x00FF00FF00FF00FFULL) + ((x >> 8) & 0x00FF00FF00FF00FFULL); + x = (x & 0x0000FFFF0000FFFFULL) + ((x >> 16) & 0x0000FFFF0000FFFFULL); + x = (x & 0x00000000FFFFFFFFULL) + ((x >> 32)); + + return x; +} + +void helper_msa_pcnt_b(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + pwd->b[0] = msa_pcnt_df(DF_BYTE, pws->b[0]); + pwd->b[1] = msa_pcnt_df(DF_BYTE, pws->b[1]); + pwd->b[2] = msa_pcnt_df(DF_BYTE, pws->b[2]); + pwd->b[3] = msa_pcnt_df(DF_BYTE, pws->b[3]); + pwd->b[4] = msa_pcnt_df(DF_BYTE, pws->b[4]); + pwd->b[5] = msa_pcnt_df(DF_BYTE, pws->b[5]); + pwd->b[6] = msa_pcnt_df(DF_BYTE, pws->b[6]); + pwd->b[7] = msa_pcnt_df(DF_BYTE, pws->b[7]); + pwd->b[8] = msa_pcnt_df(DF_BYTE, pws->b[8]); + pwd->b[9] = msa_pcnt_df(DF_BYTE, pws->b[9]); + pwd->b[10] = msa_pcnt_df(DF_BYTE, pws->b[10]); + pwd->b[11] = msa_pcnt_df(DF_BYTE, pws->b[11]); + pwd->b[12] = msa_pcnt_df(DF_BYTE, pws->b[12]); + pwd->b[13] = msa_pcnt_df(DF_BYTE, pws->b[13]); + pwd->b[14] = msa_pcnt_df(DF_BYTE, pws->b[14]); + pwd->b[15] = msa_pcnt_df(DF_BYTE, pws->b[15]); +} + +void helper_msa_pcnt_h(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + pwd->h[0] = msa_pcnt_df(DF_HALF, pws->h[0]); + pwd->h[1] = msa_pcnt_df(DF_HALF, pws->h[1]); + pwd->h[2] = msa_pcnt_df(DF_HALF, pws->h[2]); + pwd->h[3] = msa_pcnt_df(DF_HALF, pws->h[3]); + pwd->h[4] = msa_pcnt_df(DF_HALF, pws->h[4]); + pwd->h[5] = msa_pcnt_df(DF_HALF, pws->h[5]); + pwd->h[6] = msa_pcnt_df(DF_HALF, pws->h[6]); + pwd->h[7] = msa_pcnt_df(DF_HALF, pws->h[7]); +} + +void helper_msa_pcnt_w(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + pwd->w[0] = msa_pcnt_df(DF_WORD, pws->w[0]); + pwd->w[1] = msa_pcnt_df(DF_WORD, pws->w[1]); + pwd->w[2] = msa_pcnt_df(DF_WORD, pws->w[2]); + pwd->w[3] = msa_pcnt_df(DF_WORD, pws->w[3]); +} + +void helper_msa_pcnt_d(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + pwd->d[0] = msa_pcnt_df(DF_DOUBLE, pws->d[0]); + pwd->d[1] = msa_pcnt_df(DF_DOUBLE, pws->d[1]); +} /* @@ -87,7 +301,206 @@ * +---------------+----------------------------------------------------------+ */ -/* TODO: insert Bit Move group helpers here */ +/* Data format bit position and unsigned values */ +#define BIT_POSITION(x, df) ((uint64_t)(x) % DF_BITS(df)) + +static inline int64_t msa_binsl_df(uint32_t df, + int64_t dest, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_dest = UNSIGNED(dest, df); + int32_t sh_d = BIT_POSITION(arg2, df) + 1; + int32_t sh_a = DF_BITS(df) - sh_d; + if (sh_d == DF_BITS(df)) { + return u_arg1; + } else { + return UNSIGNED(UNSIGNED(u_dest << sh_d, df) >> sh_d, df) | + UNSIGNED(UNSIGNED(u_arg1 >> sh_a, df) << sh_a, df); + } +} + +void helper_msa_binsl_b(CPUMIPSState *env, + 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); + + pwd->b[0] = msa_binsl_df(DF_BYTE, pwd->b[0], pws->b[0], pwt->b[0]); + pwd->b[1] = msa_binsl_df(DF_BYTE, pwd->b[1], pws->b[1], pwt->b[1]); + pwd->b[2] = msa_binsl_df(DF_BYTE, pwd->b[2], pws->b[2], pwt->b[2]); + pwd->b[3] = msa_binsl_df(DF_BYTE, pwd->b[3], pws->b[3], pwt->b[3]); + pwd->b[4] = msa_binsl_df(DF_BYTE, pwd->b[4], pws->b[4], pwt->b[4]); + pwd->b[5] = msa_binsl_df(DF_BYTE, pwd->b[5], pws->b[5], pwt->b[5]); + pwd->b[6] = msa_binsl_df(DF_BYTE, pwd->b[6], pws->b[6], pwt->b[6]); + pwd->b[7] = msa_binsl_df(DF_BYTE, pwd->b[7], pws->b[7], pwt->b[7]); + pwd->b[8] = msa_binsl_df(DF_BYTE, pwd->b[8], pws->b[8], pwt->b[8]); + pwd->b[9] = msa_binsl_df(DF_BYTE, pwd->b[9], pws->b[9], pwt->b[9]); + pwd->b[10] = msa_binsl_df(DF_BYTE, pwd->b[10], pws->b[10], pwt->b[10]); + pwd->b[11] = msa_binsl_df(DF_BYTE, pwd->b[11], pws->b[11], pwt->b[11]); + pwd->b[12] = msa_binsl_df(DF_BYTE, pwd->b[12], pws->b[12], pwt->b[12]); + pwd->b[13] = msa_binsl_df(DF_BYTE, pwd->b[13], pws->b[13], pwt->b[13]); + pwd->b[14] = msa_binsl_df(DF_BYTE, pwd->b[14], pws->b[14], pwt->b[14]); + pwd->b[15] = msa_binsl_df(DF_BYTE, pwd->b[15], pws->b[15], pwt->b[15]); +} + +void helper_msa_binsl_h(CPUMIPSState *env, + 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); + + pwd->h[0] = msa_binsl_df(DF_HALF, pwd->h[0], pws->h[0], pwt->h[0]); + pwd->h[1] = msa_binsl_df(DF_HALF, pwd->h[1], pws->h[1], pwt->h[1]); + pwd->h[2] = msa_binsl_df(DF_HALF, pwd->h[2], pws->h[2], pwt->h[2]); + pwd->h[3] = msa_binsl_df(DF_HALF, pwd->h[3], pws->h[3], pwt->h[3]); + pwd->h[4] = msa_binsl_df(DF_HALF, pwd->h[4], pws->h[4], pwt->h[4]); + pwd->h[5] = msa_binsl_df(DF_HALF, pwd->h[5], pws->h[5], pwt->h[5]); + pwd->h[6] = msa_binsl_df(DF_HALF, pwd->h[6], pws->h[6], pwt->h[6]); + pwd->h[7] = msa_binsl_df(DF_HALF, pwd->h[7], pws->h[7], pwt->h[7]); +} + +void helper_msa_binsl_w(CPUMIPSState *env, + 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); + + pwd->w[0] = msa_binsl_df(DF_WORD, pwd->w[0], pws->w[0], pwt->w[0]); + pwd->w[1] = msa_binsl_df(DF_WORD, pwd->w[1], pws->w[1], pwt->w[1]); + pwd->w[2] = msa_binsl_df(DF_WORD, pwd->w[2], pws->w[2], pwt->w[2]); + pwd->w[3] = msa_binsl_df(DF_WORD, pwd->w[3], pws->w[3], pwt->w[3]); +} + +void helper_msa_binsl_d(CPUMIPSState *env, + 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); + + pwd->d[0] = msa_binsl_df(DF_DOUBLE, pwd->d[0], pws->d[0], pwt->d[0]); + pwd->d[1] = msa_binsl_df(DF_DOUBLE, pwd->d[1], pws->d[1], pwt->d[1]); +} + +static inline int64_t msa_binsr_df(uint32_t df, + int64_t dest, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_dest = UNSIGNED(dest, df); + int32_t sh_d = BIT_POSITION(arg2, df) + 1; + int32_t sh_a = DF_BITS(df) - sh_d; + if (sh_d == DF_BITS(df)) { + return u_arg1; + } else { + return UNSIGNED(UNSIGNED(u_dest >> sh_d, df) << sh_d, df) | + UNSIGNED(UNSIGNED(u_arg1 << sh_a, df) >> sh_a, df); + } +} + +void helper_msa_binsr_b(CPUMIPSState *env, + 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); + + pwd->b[0] = msa_binsr_df(DF_BYTE, pwd->b[0], pws->b[0], pwt->b[0]); + pwd->b[1] = msa_binsr_df(DF_BYTE, pwd->b[1], pws->b[1], pwt->b[1]); + pwd->b[2] = msa_binsr_df(DF_BYTE, pwd->b[2], pws->b[2], pwt->b[2]); + pwd->b[3] = msa_binsr_df(DF_BYTE, pwd->b[3], pws->b[3], pwt->b[3]); + pwd->b[4] = msa_binsr_df(DF_BYTE, pwd->b[4], pws->b[4], pwt->b[4]); + pwd->b[5] = msa_binsr_df(DF_BYTE, pwd->b[5], pws->b[5], pwt->b[5]); + pwd->b[6] = msa_binsr_df(DF_BYTE, pwd->b[6], pws->b[6], pwt->b[6]); + pwd->b[7] = msa_binsr_df(DF_BYTE, pwd->b[7], pws->b[7], pwt->b[7]); + pwd->b[8] = msa_binsr_df(DF_BYTE, pwd->b[8], pws->b[8], pwt->b[8]); + pwd->b[9] = msa_binsr_df(DF_BYTE, pwd->b[9], pws->b[9], pwt->b[9]); + pwd->b[10] = msa_binsr_df(DF_BYTE, pwd->b[10], pws->b[10], pwt->b[10]); + pwd->b[11] = msa_binsr_df(DF_BYTE, pwd->b[11], pws->b[11], pwt->b[11]); + pwd->b[12] = msa_binsr_df(DF_BYTE, pwd->b[12], pws->b[12], pwt->b[12]); + pwd->b[13] = msa_binsr_df(DF_BYTE, pwd->b[13], pws->b[13], pwt->b[13]); + pwd->b[14] = msa_binsr_df(DF_BYTE, pwd->b[14], pws->b[14], pwt->b[14]); + pwd->b[15] = msa_binsr_df(DF_BYTE, pwd->b[15], pws->b[15], pwt->b[15]); +} + +void helper_msa_binsr_h(CPUMIPSState *env, + 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); + + pwd->h[0] = msa_binsr_df(DF_HALF, pwd->h[0], pws->h[0], pwt->h[0]); + pwd->h[1] = msa_binsr_df(DF_HALF, pwd->h[1], pws->h[1], pwt->h[1]); + pwd->h[2] = msa_binsr_df(DF_HALF, pwd->h[2], pws->h[2], pwt->h[2]); + pwd->h[3] = msa_binsr_df(DF_HALF, pwd->h[3], pws->h[3], pwt->h[3]); + pwd->h[4] = msa_binsr_df(DF_HALF, pwd->h[4], pws->h[4], pwt->h[4]); + pwd->h[5] = msa_binsr_df(DF_HALF, pwd->h[5], pws->h[5], pwt->h[5]); + pwd->h[6] = msa_binsr_df(DF_HALF, pwd->h[6], pws->h[6], pwt->h[6]); + pwd->h[7] = msa_binsr_df(DF_HALF, pwd->h[7], pws->h[7], pwt->h[7]); +} + +void helper_msa_binsr_w(CPUMIPSState *env, + 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); + + pwd->w[0] = msa_binsr_df(DF_WORD, pwd->w[0], pws->w[0], pwt->w[0]); + pwd->w[1] = msa_binsr_df(DF_WORD, pwd->w[1], pws->w[1], pwt->w[1]); + pwd->w[2] = msa_binsr_df(DF_WORD, pwd->w[2], pws->w[2], pwt->w[2]); + pwd->w[3] = msa_binsr_df(DF_WORD, pwd->w[3], pws->w[3], pwt->w[3]); +} + +void helper_msa_binsr_d(CPUMIPSState *env, + 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); + + pwd->d[0] = msa_binsr_df(DF_DOUBLE, pwd->d[0], pws->d[0], pwt->d[0]); + pwd->d[1] = msa_binsr_df(DF_DOUBLE, pwd->d[1], pws->d[1], pwt->d[1]); +} + +void helper_msa_bmnz_v(CPUMIPSState *env, 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); + + pwd->d[0] = UNSIGNED( \ + ((pwd->d[0] & (~pwt->d[0])) | (pws->d[0] & pwt->d[0])), DF_DOUBLE); + pwd->d[1] = UNSIGNED( \ + ((pwd->d[1] & (~pwt->d[1])) | (pws->d[1] & pwt->d[1])), DF_DOUBLE); +} + +void helper_msa_bmz_v(CPUMIPSState *env, 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); + + pwd->d[0] = UNSIGNED( \ + ((pwd->d[0] & pwt->d[0]) | (pws->d[0] & (~pwt->d[0]))), DF_DOUBLE); + pwd->d[1] = UNSIGNED( \ + ((pwd->d[1] & pwt->d[1]) | (pws->d[1] & (~pwt->d[1]))), DF_DOUBLE); +} + +void helper_msa_bsel_v(CPUMIPSState *env, 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); + + pwd->d[0] = UNSIGNED( \ + (pws->d[0] & (~pwd->d[0])) | (pwt->d[0] & pwd->d[0]), DF_DOUBLE); + pwd->d[1] = UNSIGNED( \ + (pws->d[1] & (~pwd->d[1])) | (pwt->d[1] & pwd->d[1]), DF_DOUBLE); +} /* @@ -110,42 +523,245 @@ * +---------------+----------------------------------------------------------+ */ -/* TODO: insert Bit Set group helpers here */ +static inline int64_t msa_bclr_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + int32_t b_arg2 = BIT_POSITION(arg2, df); + return UNSIGNED(arg1 & (~(1LL << b_arg2)), df); +} +void helper_msa_bclr_b(CPUMIPSState *env, 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); -/* - * Fixed Multiply - * -------------- - * - * +---------------+----------------------------------------------------------+ - * | MADD_Q.H | Vector Fixed-Point Multiply and Add (halfword) | - * | MADD_Q.W | Vector Fixed-Point Multiply and Add (word) | - * | MADDR_Q.H | Vector Fixed-Point Multiply and Add Rounded (halfword) | - * | MADDR_Q.W | Vector Fixed-Point Multiply and Add Rounded (word) | - * | MSUB_Q.H | Vector Fixed-Point Multiply and Subtr. (halfword) | - * | MSUB_Q.W | Vector Fixed-Point Multiply and Subtr. (word) | - * | MSUBR_Q.H | Vector Fixed-Point Multiply and Subtr. Rounded (halfword)| - * | MSUBR_Q.W | Vector Fixed-Point Multiply and Subtr. Rounded (word) | - * | MUL_Q.H | Vector Fixed-Point Multiply (halfword) | - * | MUL_Q.W | Vector Fixed-Point Multiply (word) | - * | MULR_Q.H | Vector Fixed-Point Multiply Rounded (halfword) | - * | MULR_Q.W | Vector Fixed-Point Multiply Rounded (word) | - * +---------------+----------------------------------------------------------+ - */ + pwd->b[0] = msa_bclr_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_bclr_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_bclr_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_bclr_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_bclr_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_bclr_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_bclr_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_bclr_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_bclr_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_bclr_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_bclr_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_bclr_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_bclr_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_bclr_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_bclr_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_bclr_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_bclr_h(CPUMIPSState *env, 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); -/* TODO: insert Fixed Multiply group helpers here */ + pwd->h[0] = msa_bclr_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_bclr_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_bclr_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_bclr_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_bclr_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_bclr_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_bclr_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_bclr_df(DF_HALF, pws->h[7], pwt->h[7]); +} +void helper_msa_bclr_w(CPUMIPSState *env, 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); -/* - * Float Max Min - * ------------- - * - * +---------------+----------------------------------------------------------+ - * | FMAX_A.W | Vector Floating-Point Maximum (Absolute) (word) | - * | FMAX_A.D | Vector Floating-Point Maximum (Absolute) (doubleword) | - * | FMAX.W | Vector Floating-Point Maximum (word) | - * | FMAX.D | Vector Floating-Point Maximum (doubleword) | - * | FMIN_A.W | Vector Floating-Point Minimum (Absolute) (word) | + pwd->w[0] = msa_bclr_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_bclr_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_bclr_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_bclr_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_bclr_d(CPUMIPSState *env, 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); + + pwd->d[0] = msa_bclr_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_bclr_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + +static inline int64_t msa_bneg_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + int32_t b_arg2 = BIT_POSITION(arg2, df); + return UNSIGNED(arg1 ^ (1LL << b_arg2), df); +} + +void helper_msa_bneg_b(CPUMIPSState *env, 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); + + pwd->b[0] = msa_bneg_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_bneg_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_bneg_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_bneg_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_bneg_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_bneg_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_bneg_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_bneg_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_bneg_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_bneg_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_bneg_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_bneg_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_bneg_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_bneg_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_bneg_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_bneg_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_bneg_h(CPUMIPSState *env, 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); + + pwd->h[0] = msa_bneg_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_bneg_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_bneg_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_bneg_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_bneg_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_bneg_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_bneg_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_bneg_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_bneg_w(CPUMIPSState *env, 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); + + pwd->w[0] = msa_bneg_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_bneg_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_bneg_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_bneg_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_bneg_d(CPUMIPSState *env, 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); + + pwd->d[0] = msa_bneg_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_bneg_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + +static inline int64_t msa_bset_df(uint32_t df, int64_t arg1, + int64_t arg2) +{ + int32_t b_arg2 = BIT_POSITION(arg2, df); + return UNSIGNED(arg1 | (1LL << b_arg2), df); +} + +void helper_msa_bset_b(CPUMIPSState *env, 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); + + pwd->b[0] = msa_bset_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_bset_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_bset_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_bset_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_bset_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_bset_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_bset_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_bset_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_bset_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_bset_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_bset_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_bset_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_bset_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_bset_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_bset_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_bset_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_bset_h(CPUMIPSState *env, 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); + + pwd->h[0] = msa_bset_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_bset_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_bset_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_bset_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_bset_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_bset_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_bset_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_bset_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_bset_w(CPUMIPSState *env, 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); + + pwd->w[0] = msa_bset_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_bset_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_bset_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_bset_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_bset_d(CPUMIPSState *env, 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); + + pwd->d[0] = msa_bset_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_bset_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + + +/* + * Fixed Multiply + * -------------- + * + * +---------------+----------------------------------------------------------+ + * | MADD_Q.H | Vector Fixed-Point Multiply and Add (halfword) | + * | MADD_Q.W | Vector Fixed-Point Multiply and Add (word) | + * | MADDR_Q.H | Vector Fixed-Point Multiply and Add Rounded (halfword) | + * | MADDR_Q.W | Vector Fixed-Point Multiply and Add Rounded (word) | + * | MSUB_Q.H | Vector Fixed-Point Multiply and Subtr. (halfword) | + * | MSUB_Q.W | Vector Fixed-Point Multiply and Subtr. (word) | + * | MSUBR_Q.H | Vector Fixed-Point Multiply and Subtr. Rounded (halfword)| + * | MSUBR_Q.W | Vector Fixed-Point Multiply and Subtr. Rounded (word) | + * | MUL_Q.H | Vector Fixed-Point Multiply (halfword) | + * | MUL_Q.W | Vector Fixed-Point Multiply (word) | + * | MULR_Q.H | Vector Fixed-Point Multiply Rounded (halfword) | + * | MULR_Q.W | Vector Fixed-Point Multiply Rounded (word) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Fixed Multiply group helpers here */ + + +/* + * Float Max Min + * ------------- + * + * +---------------+----------------------------------------------------------+ + * | FMAX_A.W | Vector Floating-Point Maximum (Absolute) (word) | + * | FMAX_A.D | Vector Floating-Point Maximum (Absolute) (doubleword) | + * | FMAX.W | Vector Floating-Point Maximum (word) | + * | FMAX.D | Vector Floating-Point Maximum (doubleword) | + * | FMIN_A.W | Vector Floating-Point Minimum (Absolute) (word) | * | FMIN_A.D | Vector Floating-Point Minimum (Absolute) (doubleword) | * | FMIN.W | Vector Floating-Point Minimum (word) | * | FMIN.D | Vector Floating-Point Minimum (doubleword) | @@ -216,57 +832,847 @@ * +---------------+----------------------------------------------------------+ */ -/* TODO: insert Int Average group helpers here */ +static inline int64_t msa_ave_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + /* signed shift */ + return (arg1 >> 1) + (arg2 >> 1) + (arg1 & arg2 & 1); +} + +void helper_msa_ave_s_b(CPUMIPSState *env, + 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); + + pwd->b[0] = msa_ave_s_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_ave_s_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_ave_s_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_ave_s_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_ave_s_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_ave_s_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_ave_s_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_ave_s_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_ave_s_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_ave_s_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_ave_s_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_ave_s_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_ave_s_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_ave_s_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_ave_s_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_ave_s_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_ave_s_h(CPUMIPSState *env, + 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); + + pwd->h[0] = msa_ave_s_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_ave_s_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_ave_s_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_ave_s_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_ave_s_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_ave_s_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_ave_s_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_ave_s_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_ave_s_w(CPUMIPSState *env, + 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); + + pwd->w[0] = msa_ave_s_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_ave_s_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_ave_s_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_ave_s_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_ave_s_d(CPUMIPSState *env, + 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); + + pwd->d[0] = msa_ave_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_ave_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + +static inline uint64_t msa_ave_u_df(uint32_t df, uint64_t arg1, uint64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + /* unsigned shift */ + return (u_arg1 >> 1) + (u_arg2 >> 1) + (u_arg1 & u_arg2 & 1); +} + +void helper_msa_ave_u_b(CPUMIPSState *env, + 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); + + pwd->b[0] = msa_ave_u_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_ave_u_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_ave_u_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_ave_u_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_ave_u_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_ave_u_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_ave_u_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_ave_u_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_ave_u_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_ave_u_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_ave_u_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_ave_u_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_ave_u_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_ave_u_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_ave_u_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_ave_u_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_ave_u_h(CPUMIPSState *env, + 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); + + pwd->h[0] = msa_ave_u_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_ave_u_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_ave_u_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_ave_u_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_ave_u_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_ave_u_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_ave_u_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_ave_u_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_ave_u_w(CPUMIPSState *env, + 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); + + pwd->w[0] = msa_ave_u_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_ave_u_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_ave_u_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_ave_u_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_ave_u_d(CPUMIPSState *env, + 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); + + pwd->d[0] = msa_ave_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_ave_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + +static inline int64_t msa_aver_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + /* signed shift */ + return (arg1 >> 1) + (arg2 >> 1) + ((arg1 | arg2) & 1); +} + +void helper_msa_aver_s_b(CPUMIPSState *env, + 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); + + pwd->b[0] = msa_aver_s_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_aver_s_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_aver_s_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_aver_s_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_aver_s_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_aver_s_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_aver_s_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_aver_s_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_aver_s_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_aver_s_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_aver_s_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_aver_s_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_aver_s_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_aver_s_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_aver_s_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_aver_s_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_aver_s_h(CPUMIPSState *env, + 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); + + pwd->h[0] = msa_aver_s_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_aver_s_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_aver_s_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_aver_s_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_aver_s_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_aver_s_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_aver_s_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_aver_s_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_aver_s_w(CPUMIPSState *env, + 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); + + pwd->w[0] = msa_aver_s_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_aver_s_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_aver_s_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_aver_s_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_aver_s_d(CPUMIPSState *env, + 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); + + pwd->d[0] = msa_aver_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_aver_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + +static inline uint64_t msa_aver_u_df(uint32_t df, uint64_t arg1, uint64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + /* unsigned shift */ + return (u_arg1 >> 1) + (u_arg2 >> 1) + ((u_arg1 | u_arg2) & 1); +} + +void helper_msa_aver_u_b(CPUMIPSState *env, + 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); + + pwd->b[0] = msa_aver_u_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_aver_u_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_aver_u_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_aver_u_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_aver_u_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_aver_u_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_aver_u_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_aver_u_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_aver_u_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_aver_u_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_aver_u_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_aver_u_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_aver_u_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_aver_u_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_aver_u_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_aver_u_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_aver_u_h(CPUMIPSState *env, + 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); + + pwd->h[0] = msa_aver_u_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_aver_u_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_aver_u_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_aver_u_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_aver_u_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_aver_u_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_aver_u_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_aver_u_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_aver_u_w(CPUMIPSState *env, + 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); + + pwd->w[0] = msa_aver_u_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_aver_u_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_aver_u_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_aver_u_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_aver_u_d(CPUMIPSState *env, + 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); + + pwd->d[0] = msa_aver_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_aver_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + + +/* + * Int Compare + * ----------- + * + * +---------------+----------------------------------------------------------+ + * | CEQ.B | Vector Compare Equal (byte) | + * | CEQ.H | Vector Compare Equal (halfword) | + * | CEQ.W | Vector Compare Equal (word) | + * | CEQ.D | Vector Compare Equal (doubleword) | + * | CLE_S.B | Vector Compare Signed Less Than or Equal (byte) | + * | CLE_S.H | Vector Compare Signed Less Than or Equal (halfword) | + * | CLE_S.W | Vector Compare Signed Less Than or Equal (word) | + * | CLE_S.D | Vector Compare Signed Less Than or Equal (doubleword) | + * | CLE_U.B | Vector Compare Unsigned Less Than or Equal (byte) | + * | CLE_U.H | Vector Compare Unsigned Less Than or Equal (halfword) | + * | CLE_U.W | Vector Compare Unsigned Less Than or Equal (word) | + * | CLE_U.D | Vector Compare Unsigned Less Than or Equal (doubleword) | + * | CLT_S.B | Vector Compare Signed Less Than (byte) | + * | CLT_S.H | Vector Compare Signed Less Than (halfword) | + * | CLT_S.W | Vector Compare Signed Less Than (word) | + * | CLT_S.D | Vector Compare Signed Less Than (doubleword) | + * | CLT_U.B | Vector Compare Unsigned Less Than (byte) | + * | CLT_U.H | Vector Compare Unsigned Less Than (halfword) | + * | CLT_U.W | Vector Compare Unsigned Less Than (word) | + * | CLT_U.D | Vector Compare Unsigned Less Than (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +static inline int64_t msa_ceq_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + return arg1 == arg2 ? -1 : 0; +} + +void helper_msa_ceq_b(CPUMIPSState *env, 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); + + pwd->b[0] = msa_ceq_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_ceq_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_ceq_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_ceq_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_ceq_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_ceq_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_ceq_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_ceq_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_ceq_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_ceq_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_ceq_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_ceq_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_ceq_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_ceq_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_ceq_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_ceq_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_ceq_h(CPUMIPSState *env, 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); + + pwd->h[0] = msa_ceq_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_ceq_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_ceq_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_ceq_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_ceq_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_ceq_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_ceq_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_ceq_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_ceq_w(CPUMIPSState *env, 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); + + pwd->w[0] = msa_ceq_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_ceq_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_ceq_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_ceq_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_ceq_d(CPUMIPSState *env, 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); + + pwd->d[0] = msa_ceq_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_ceq_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + +static inline int64_t msa_cle_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + return arg1 <= arg2 ? -1 : 0; +} + +void helper_msa_cle_s_b(CPUMIPSState *env, + 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); + + pwd->b[0] = msa_cle_s_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_cle_s_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_cle_s_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_cle_s_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_cle_s_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_cle_s_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_cle_s_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_cle_s_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_cle_s_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_cle_s_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_cle_s_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_cle_s_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_cle_s_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_cle_s_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_cle_s_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_cle_s_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_cle_s_h(CPUMIPSState *env, + 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); + + pwd->h[0] = msa_cle_s_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_cle_s_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_cle_s_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_cle_s_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_cle_s_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_cle_s_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_cle_s_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_cle_s_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_cle_s_w(CPUMIPSState *env, + 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); + + pwd->w[0] = msa_cle_s_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_cle_s_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_cle_s_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_cle_s_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_cle_s_d(CPUMIPSState *env, + 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); + + pwd->d[0] = msa_cle_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_cle_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + +static inline int64_t msa_cle_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + return u_arg1 <= u_arg2 ? -1 : 0; +} + +void helper_msa_cle_u_b(CPUMIPSState *env, + 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); + + pwd->b[0] = msa_cle_u_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_cle_u_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_cle_u_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_cle_u_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_cle_u_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_cle_u_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_cle_u_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_cle_u_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_cle_u_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_cle_u_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_cle_u_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_cle_u_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_cle_u_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_cle_u_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_cle_u_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_cle_u_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_cle_u_h(CPUMIPSState *env, + 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); + + pwd->h[0] = msa_cle_u_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_cle_u_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_cle_u_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_cle_u_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_cle_u_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_cle_u_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_cle_u_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_cle_u_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_cle_u_w(CPUMIPSState *env, + 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); + + pwd->w[0] = msa_cle_u_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_cle_u_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_cle_u_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_cle_u_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_cle_u_d(CPUMIPSState *env, + 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); + + pwd->d[0] = msa_cle_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_cle_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + +static inline int64_t msa_clt_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + return arg1 < arg2 ? -1 : 0; +} + +void helper_msa_clt_s_b(CPUMIPSState *env, + 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); + + pwd->b[0] = msa_clt_s_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_clt_s_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_clt_s_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_clt_s_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_clt_s_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_clt_s_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_clt_s_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_clt_s_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_clt_s_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_clt_s_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_clt_s_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_clt_s_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_clt_s_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_clt_s_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_clt_s_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_clt_s_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_clt_s_h(CPUMIPSState *env, + 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); + + pwd->h[0] = msa_clt_s_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_clt_s_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_clt_s_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_clt_s_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_clt_s_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_clt_s_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_clt_s_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_clt_s_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_clt_s_w(CPUMIPSState *env, + 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); + + pwd->w[0] = msa_clt_s_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_clt_s_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_clt_s_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_clt_s_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_clt_s_d(CPUMIPSState *env, + 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); + + pwd->d[0] = msa_clt_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_clt_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + +static inline int64_t msa_clt_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + return u_arg1 < u_arg2 ? -1 : 0; +} + +void helper_msa_clt_u_b(CPUMIPSState *env, + 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); + + pwd->b[0] = msa_clt_u_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_clt_u_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_clt_u_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_clt_u_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_clt_u_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_clt_u_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_clt_u_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_clt_u_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_clt_u_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_clt_u_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_clt_u_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_clt_u_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_clt_u_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_clt_u_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_clt_u_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_clt_u_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_clt_u_h(CPUMIPSState *env, + 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); + + pwd->h[0] = msa_clt_u_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_clt_u_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_clt_u_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_clt_u_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_clt_u_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_clt_u_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_clt_u_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_clt_u_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_clt_u_w(CPUMIPSState *env, + 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); + + pwd->w[0] = msa_clt_u_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_clt_u_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_clt_u_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_clt_u_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_clt_u_d(CPUMIPSState *env, + 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); + + pwd->d[0] = msa_clt_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_clt_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + + +/* + * Int Divide + * ---------- + * + * +---------------+----------------------------------------------------------+ + * | DIV_S.B | Vector Signed Divide (byte) | + * | DIV_S.H | Vector Signed Divide (halfword) | + * | DIV_S.W | Vector Signed Divide (word) | + * | DIV_S.D | Vector Signed Divide (doubleword) | + * | DIV_U.B | Vector Unsigned Divide (byte) | + * | DIV_U.H | Vector Unsigned Divide (halfword) | + * | DIV_U.W | Vector Unsigned Divide (word) | + * | DIV_U.D | Vector Unsigned Divide (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + + +static inline int64_t msa_div_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + if (arg1 == DF_MIN_INT(df) && arg2 == -1) { + return DF_MIN_INT(df); + } + return arg2 ? arg1 / arg2 + : arg1 >= 0 ? -1 : 1; +} + +void helper_msa_div_s_b(CPUMIPSState *env, + 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); + + pwd->b[0] = msa_div_s_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_div_s_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_div_s_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_div_s_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_div_s_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_div_s_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_div_s_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_div_s_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_div_s_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_div_s_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_div_s_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_div_s_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_div_s_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_div_s_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_div_s_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_div_s_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_div_s_h(CPUMIPSState *env, + 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); + + pwd->h[0] = msa_div_s_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_div_s_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_div_s_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_div_s_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_div_s_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_div_s_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_div_s_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_div_s_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_div_s_w(CPUMIPSState *env, + 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); + + pwd->w[0] = msa_div_s_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_div_s_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_div_s_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_div_s_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_div_s_d(CPUMIPSState *env, + 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); + + pwd->d[0] = msa_div_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_div_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + +static inline int64_t msa_div_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + return arg2 ? u_arg1 / u_arg2 : -1; +} + +void helper_msa_div_u_b(CPUMIPSState *env, + 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); + pwd->b[0] = msa_div_u_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_div_u_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_div_u_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_div_u_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_div_u_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_div_u_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_div_u_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_div_u_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_div_u_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_div_u_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_div_u_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_div_u_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_div_u_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_div_u_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_div_u_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_div_u_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_div_u_h(CPUMIPSState *env, + 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); -/* - * Int Compare - * ----------- - * - * +---------------+----------------------------------------------------------+ - * | CEQ.B | Vector Compare Equal (byte) | - * | CEQ.H | Vector Compare Equal (halfword) | - * | CEQ.W | Vector Compare Equal (word) | - * | CEQ.D | Vector Compare Equal (doubleword) | - * | CLE_S.B | Vector Compare Signed Less Than or Equal (byte) | - * | CLE_S.H | Vector Compare Signed Less Than or Equal (halfword) | - * | CLE_S.W | Vector Compare Signed Less Than or Equal (word) | - * | CLE_S.D | Vector Compare Signed Less Than or Equal (doubleword) | - * | CLE_U.B | Vector Compare Unsigned Less Than or Equal (byte) | - * | CLE_U.H | Vector Compare Unsigned Less Than or Equal (halfword) | - * | CLE_U.W | Vector Compare Unsigned Less Than or Equal (word) | - * | CLE_U.D | Vector Compare Unsigned Less Than or Equal (doubleword) | - * | CLT_S.B | Vector Compare Signed Less Than (byte) | - * | CLT_S.H | Vector Compare Signed Less Than (halfword) | - * | CLT_S.W | Vector Compare Signed Less Than (word) | - * | CLT_S.D | Vector Compare Signed Less Than (doubleword) | - * | CLT_U.B | Vector Compare Unsigned Less Than (byte) | - * | CLT_U.H | Vector Compare Unsigned Less Than (halfword) | - * | CLT_U.W | Vector Compare Unsigned Less Than (word) | - * | CLT_U.D | Vector Compare Unsigned Less Than (doubleword) | - * +---------------+----------------------------------------------------------+ - */ + pwd->h[0] = msa_div_u_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_div_u_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_div_u_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_div_u_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_div_u_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_div_u_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_div_u_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_div_u_df(DF_HALF, pws->h[7], pwt->h[7]); +} -/* TODO: insert Int Compare group helpers here */ +void helper_msa_div_u_w(CPUMIPSState *env, + 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); + pwd->w[0] = msa_div_u_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_div_u_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_div_u_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_div_u_df(DF_WORD, pws->w[3], pwt->w[3]); +} -/* - * Int Divide - * ---------- - * - * +---------------+----------------------------------------------------------+ - * | DIV_S.B | Vector Signed Divide (byte) | - * | DIV_S.H | Vector Signed Divide (halfword) | - * | DIV_S.W | Vector Signed Divide (word) | - * | DIV_S.D | Vector Signed Divide (doubleword) | - * | DIV_U.B | Vector Unsigned Divide (byte) | - * | DIV_U.H | Vector Unsigned Divide (halfword) | - * | DIV_U.W | Vector Unsigned Divide (word) | - * | DIV_U.D | Vector Unsigned Divide (doubleword) | - * +---------------+----------------------------------------------------------+ - */ +void helper_msa_div_u_d(CPUMIPSState *env, + 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); -/* TODO: insert Int Divide group helpers here */ + pwd->d[0] = msa_div_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_div_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} /* @@ -349,7 +1755,152 @@ * +---------------+----------------------------------------------------------+ */ -/* TODO: insert Int Modulo group helpers here */ +static inline int64_t msa_mod_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + if (arg1 == DF_MIN_INT(df) && arg2 == -1) { + return 0; + } + return arg2 ? arg1 % arg2 : arg1; +} + +void helper_msa_mod_s_b(CPUMIPSState *env, + 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); + + pwd->b[0] = msa_mod_s_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_mod_s_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_mod_s_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_mod_s_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_mod_s_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_mod_s_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_mod_s_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_mod_s_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_mod_s_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_mod_s_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_mod_s_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_mod_s_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_mod_s_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_mod_s_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_mod_s_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_mod_s_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_mod_s_h(CPUMIPSState *env, + 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); + + pwd->h[0] = msa_mod_s_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_mod_s_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_mod_s_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_mod_s_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_mod_s_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_mod_s_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_mod_s_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_mod_s_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_mod_s_w(CPUMIPSState *env, + 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); + + pwd->w[0] = msa_mod_s_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_mod_s_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_mod_s_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_mod_s_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_mod_s_d(CPUMIPSState *env, + 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); + + pwd->d[0] = msa_mod_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_mod_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + +static inline int64_t msa_mod_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + return u_arg2 ? u_arg1 % u_arg2 : u_arg1; +} + +void helper_msa_mod_u_b(CPUMIPSState *env, + 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); + + pwd->b[0] = msa_mod_u_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_mod_u_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_mod_u_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_mod_u_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_mod_u_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_mod_u_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_mod_u_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_mod_u_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_mod_u_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_mod_u_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_mod_u_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_mod_u_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_mod_u_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_mod_u_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_mod_u_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_mod_u_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_mod_u_h(CPUMIPSState *env, + 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); + + pwd->h[0] = msa_mod_u_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_mod_u_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_mod_u_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_mod_u_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_mod_u_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_mod_u_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_mod_u_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_mod_u_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_mod_u_w(CPUMIPSState *env, + 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); + + pwd->w[0] = msa_mod_u_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_mod_u_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_mod_u_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_mod_u_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_mod_u_d(CPUMIPSState *env, + 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); + + pwd->d[0] = msa_mod_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_mod_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} /* @@ -459,7 +2010,46 @@ * +---------------+----------------------------------------------------------+ */ -/* TODO: insert Logic group helpers here */ + +void helper_msa_and_v(CPUMIPSState *env, 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); + + pwd->d[0] = pws->d[0] & pwt->d[0]; + pwd->d[1] = pws->d[1] & pwt->d[1]; +} + +void helper_msa_nor_v(CPUMIPSState *env, 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); + + pwd->d[0] = ~(pws->d[0] | pwt->d[0]); + pwd->d[1] = ~(pws->d[1] | pwt->d[1]); +} + +void helper_msa_or_v(CPUMIPSState *env, 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); + + pwd->d[0] = pws->d[0] | pwt->d[0]; + pwd->d[1] = pws->d[1] | pwt->d[1]; +} + +void helper_msa_xor_v(CPUMIPSState *env, 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); + + pwd->d[0] = pws->d[0] ^ pwt->d[0]; + pwd->d[1] = pws->d[1] ^ pwt->d[1]; +} /* @@ -471,7 +2061,19 @@ * +---------------+----------------------------------------------------------+ */ -/* TODO: insert Move group helpers here */ +static inline void msa_move_v(wr_t *pwd, wr_t *pws) +{ + pwd->d[0] = pws->d[0]; + pwd->d[1] = pws->d[1]; +} + +void helper_msa_move_v(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + msa_move_v(pwd, pws); +} /* @@ -528,15 +2130,6 @@ /* TODO: insert Shift group helpers here */ -static inline void msa_move_v(wr_t *pwd, wr_t *pws) -{ - uint32_t i; - - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { - pwd->d[i] = pws->d[i]; - } -} - #define MSA_FN_IMM8(FUNC, DEST, OPERATION) \ void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \ uint32_t i8) \ @@ -562,109 +2155,48 @@ MSA_FN_IMM8(bmnzi_b, pwd->b[i], #define BIT_MOVE_IF_ZERO(dest, arg1, arg2, df) \ UNSIGNED((dest & arg2) | (arg1 & (~arg2)), df) MSA_FN_IMM8(bmzi_b, pwd->b[i], - BIT_MOVE_IF_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE)) - -#define BIT_SELECT(dest, arg1, arg2, df) \ - UNSIGNED((arg1 & (~dest)) | (arg2 & dest), df) -MSA_FN_IMM8(bseli_b, pwd->b[i], - BIT_SELECT(pwd->b[i], pws->b[i], i8, DF_BYTE)) - -#undef MSA_FN_IMM8 - -#define SHF_POS(i, imm) (((i) & 0xfc) + (((imm) >> (2 * ((i) & 0x03))) & 0x03)) - -void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, - uint32_t ws, uint32_t imm) -{ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - wr_t *pws = &(env->active_fpu.fpr[ws].wr); - wr_t wx, *pwx = &wx; - uint32_t i; - - switch (df) { - case DF_BYTE: - for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { - pwx->b[i] = pws->b[SHF_POS(i, imm)]; - } - break; - case DF_HALF: - for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { - pwx->h[i] = pws->h[SHF_POS(i, imm)]; - } - break; - case DF_WORD: - for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { - pwx->w[i] = pws->w[SHF_POS(i, imm)]; - } - break; - default: - assert(0); - } - msa_move_v(pwd, pwx); -} - -#define MSA_FN_VECTOR(FUNC, DEST, OPERATION) \ -void helper_msa_ ## FUNC(CPUMIPSState *env, 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; \ - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \ - DEST = OPERATION; \ - } \ -} - -MSA_FN_VECTOR(bmnz_v, pwd->d[i], - BIT_MOVE_IF_NOT_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE)) -MSA_FN_VECTOR(bmz_v, pwd->d[i], - BIT_MOVE_IF_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE)) -MSA_FN_VECTOR(bsel_v, pwd->d[i], - BIT_SELECT(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE)) -#undef BIT_MOVE_IF_NOT_ZERO -#undef BIT_MOVE_IF_ZERO -#undef BIT_SELECT -#undef MSA_FN_VECTOR - -void helper_msa_and_v(CPUMIPSState *env, 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); - - pwd->d[0] = pws->d[0] & pwt->d[0]; - pwd->d[1] = pws->d[1] & pwt->d[1]; -} - -void helper_msa_or_v(CPUMIPSState *env, 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); + BIT_MOVE_IF_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE)) - pwd->d[0] = pws->d[0] | pwt->d[0]; - pwd->d[1] = pws->d[1] | pwt->d[1]; -} +#define BIT_SELECT(dest, arg1, arg2, df) \ + UNSIGNED((arg1 & (~dest)) | (arg2 & dest), df) +MSA_FN_IMM8(bseli_b, pwd->b[i], + BIT_SELECT(pwd->b[i], pws->b[i], i8, DF_BYTE)) -void helper_msa_nor_v(CPUMIPSState *env, 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); +#undef BIT_SELECT +#undef BIT_MOVE_IF_ZERO +#undef BIT_MOVE_IF_NOT_ZERO +#undef MSA_FN_IMM8 - pwd->d[0] = ~(pws->d[0] | pwt->d[0]); - pwd->d[1] = ~(pws->d[1] | pwt->d[1]); -} +#define SHF_POS(i, imm) (((i) & 0xfc) + (((imm) >> (2 * ((i) & 0x03))) & 0x03)) -void helper_msa_xor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt) +void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t imm) { 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); + wr_t wx, *pwx = &wx; + uint32_t i; - pwd->d[0] = pws->d[0] ^ pwt->d[0]; - pwd->d[1] = pws->d[1] ^ pwt->d[1]; + switch (df) { + case DF_BYTE: + for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { + pwx->b[i] = pws->b[SHF_POS(i, imm)]; + } + break; + case DF_HALF: + for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { + pwx->h[i] = pws->h[SHF_POS(i, imm)]; + } + break; + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + pwx->w[i] = pws->w[SHF_POS(i, imm)]; + } + break; + default: + assert(0); + } + msa_move_v(pwd, pwx); } static inline int64_t msa_addv_df(uint32_t df, int64_t arg1, int64_t arg2) @@ -677,35 +2209,6 @@ static inline int64_t msa_subv_df(uint32_t df, int64_t arg1, int64_t arg2) return arg1 - arg2; } -static inline int64_t msa_ceq_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - return arg1 == arg2 ? -1 : 0; -} - -static inline int64_t msa_cle_s_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - return arg1 <= arg2 ? -1 : 0; -} - -static inline int64_t msa_cle_u_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - uint64_t u_arg1 = UNSIGNED(arg1, df); - uint64_t u_arg2 = UNSIGNED(arg2, df); - return u_arg1 <= u_arg2 ? -1 : 0; -} - -static inline int64_t msa_clt_s_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - return arg1 < arg2 ? -1 : 0; -} - -static inline int64_t msa_clt_u_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - uint64_t u_arg1 = UNSIGNED(arg1, df); - uint64_t u_arg2 = UNSIGNED(arg2, df); - return u_arg1 < u_arg2 ? -1 : 0; -} - static inline int64_t msa_max_s_df(uint32_t df, int64_t arg1, int64_t arg2) { return arg1 > arg2 ? arg1 : arg2; @@ -809,9 +2312,6 @@ void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, } } -/* Data format bit position and unsigned values */ -#define BIT_POSITION(x, df) ((uint64_t)(x) % DF_BITS(df)) - static inline int64_t msa_sll_df(uint32_t df, int64_t arg1, int64_t arg2) { int32_t b_arg2 = BIT_POSITION(arg2, df); @@ -831,55 +2331,6 @@ static inline int64_t msa_srl_df(uint32_t df, int64_t arg1, int64_t arg2) return u_arg1 >> b_arg2; } -static inline int64_t msa_bclr_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - int32_t b_arg2 = BIT_POSITION(arg2, df); - return UNSIGNED(arg1 & (~(1LL << b_arg2)), df); -} - -static inline int64_t msa_bset_df(uint32_t df, int64_t arg1, - int64_t arg2) -{ - int32_t b_arg2 = BIT_POSITION(arg2, df); - return UNSIGNED(arg1 | (1LL << b_arg2), df); -} - -static inline int64_t msa_bneg_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - int32_t b_arg2 = BIT_POSITION(arg2, df); - return UNSIGNED(arg1 ^ (1LL << b_arg2), df); -} - -static inline int64_t msa_binsl_df(uint32_t df, int64_t dest, int64_t arg1, - int64_t arg2) -{ - uint64_t u_arg1 = UNSIGNED(arg1, df); - uint64_t u_dest = UNSIGNED(dest, df); - int32_t sh_d = BIT_POSITION(arg2, df) + 1; - int32_t sh_a = DF_BITS(df) - sh_d; - if (sh_d == DF_BITS(df)) { - return u_arg1; - } else { - return UNSIGNED(UNSIGNED(u_dest << sh_d, df) >> sh_d, df) | - UNSIGNED(UNSIGNED(u_arg1 >> sh_a, df) << sh_a, df); - } -} - -static inline int64_t msa_binsr_df(uint32_t df, int64_t dest, int64_t arg1, - int64_t arg2) -{ - uint64_t u_arg1 = UNSIGNED(arg1, df); - uint64_t u_dest = UNSIGNED(dest, df); - int32_t sh_d = BIT_POSITION(arg2, df) + 1; - int32_t sh_a = DF_BITS(df) - sh_d; - if (sh_d == DF_BITS(df)) { - return u_arg1; - } else { - return UNSIGNED(UNSIGNED(u_dest >> sh_d, df) << sh_d, df) | - UNSIGNED(UNSIGNED(u_arg1 << sh_a, df) >> sh_a, df); - } -} - static inline int64_t msa_sat_s_df(uint32_t df, int64_t arg, uint32_t m) { return arg < M_MIN_INT(m + 1) ? M_MIN_INT(m + 1) : @@ -1057,34 +2508,6 @@ static inline uint64_t msa_adds_u_df(uint32_t df, uint64_t arg1, uint64_t arg2) return (u_arg1 < max_uint - u_arg2) ? u_arg1 + u_arg2 : max_uint; } -static inline int64_t msa_ave_s_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - /* signed shift */ - return (arg1 >> 1) + (arg2 >> 1) + (arg1 & arg2 & 1); -} - -static inline uint64_t msa_ave_u_df(uint32_t df, uint64_t arg1, uint64_t arg2) -{ - uint64_t u_arg1 = UNSIGNED(arg1, df); - uint64_t u_arg2 = UNSIGNED(arg2, df); - /* unsigned shift */ - return (u_arg1 >> 1) + (u_arg2 >> 1) + (u_arg1 & u_arg2 & 1); -} - -static inline int64_t msa_aver_s_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - /* signed shift */ - return (arg1 >> 1) + (arg2 >> 1) + ((arg1 | arg2) & 1); -} - -static inline uint64_t msa_aver_u_df(uint32_t df, uint64_t arg1, uint64_t arg2) -{ - uint64_t u_arg1 = UNSIGNED(arg1, df); - uint64_t u_arg2 = UNSIGNED(arg2, df); - /* unsigned shift */ - return (u_arg1 >> 1) + (u_arg2 >> 1) + ((u_arg1 | u_arg2) & 1); -} - static inline int64_t msa_subs_s_df(uint32_t df, int64_t arg1, int64_t arg2) { int64_t max_int = DF_MAX_INT(df); @@ -1158,37 +2581,6 @@ static inline int64_t msa_mulv_df(uint32_t df, int64_t arg1, int64_t arg2) return arg1 * arg2; } -static inline int64_t msa_div_s_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - if (arg1 == DF_MIN_INT(df) && arg2 == -1) { - return DF_MIN_INT(df); - } - return arg2 ? arg1 / arg2 - : arg1 >= 0 ? -1 : 1; -} - -static inline int64_t msa_div_u_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - uint64_t u_arg1 = UNSIGNED(arg1, df); - uint64_t u_arg2 = UNSIGNED(arg2, df); - return arg2 ? u_arg1 / u_arg2 : -1; -} - -static inline int64_t msa_mod_s_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - if (arg1 == DF_MIN_INT(df) && arg2 == -1) { - return 0; - } - return arg2 ? arg1 % arg2 : arg1; -} - -static inline int64_t msa_mod_u_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - uint64_t u_arg1 = UNSIGNED(arg1, df); - uint64_t u_arg2 = UNSIGNED(arg2, df); - return u_arg2 ? u_arg1 % u_arg2 : u_arg1; -} - #define SIGNED_EVEN(a, df) \ ((((int64_t)(a)) << (64 - DF_BITS(df) / 2)) >> (64 - DF_BITS(df) / 2)) @@ -1375,9 +2767,6 @@ void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \ MSA_BINOP_DF(sll) MSA_BINOP_DF(sra) MSA_BINOP_DF(srl) -MSA_BINOP_DF(bclr) -MSA_BINOP_DF(bset) -MSA_BINOP_DF(bneg) MSA_BINOP_DF(addv) MSA_BINOP_DF(subv) MSA_BINOP_DF(max_s) @@ -1386,19 +2775,10 @@ MSA_BINOP_DF(min_s) MSA_BINOP_DF(min_u) MSA_BINOP_DF(max_a) MSA_BINOP_DF(min_a) -MSA_BINOP_DF(ceq) -MSA_BINOP_DF(clt_s) -MSA_BINOP_DF(clt_u) -MSA_BINOP_DF(cle_s) -MSA_BINOP_DF(cle_u) MSA_BINOP_DF(add_a) MSA_BINOP_DF(adds_a) MSA_BINOP_DF(adds_s) MSA_BINOP_DF(adds_u) -MSA_BINOP_DF(ave_s) -MSA_BINOP_DF(ave_u) -MSA_BINOP_DF(aver_s) -MSA_BINOP_DF(aver_u) MSA_BINOP_DF(subs_s) MSA_BINOP_DF(subs_u) MSA_BINOP_DF(subsus_u) @@ -1406,10 +2786,6 @@ MSA_BINOP_DF(subsuu_s) MSA_BINOP_DF(asub_s) MSA_BINOP_DF(asub_u) MSA_BINOP_DF(mulv) -MSA_BINOP_DF(div_s) -MSA_BINOP_DF(div_u) -MSA_BINOP_DF(mod_s) -MSA_BINOP_DF(mod_u) MSA_BINOP_DF(dotp_s) MSA_BINOP_DF(dotp_u) MSA_BINOP_DF(srar) @@ -2500,56 +3876,6 @@ target_ulong helper_msa_cfcmsa(CPUMIPSState *env, uint32_t cs) return 0; } -void helper_msa_move_v(CPUMIPSState *env, uint32_t wd, uint32_t ws) -{ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - wr_t *pws = &(env->active_fpu.fpr[ws].wr); - - msa_move_v(pwd, pws); -} - -static inline int64_t msa_pcnt_df(uint32_t df, int64_t arg) -{ - uint64_t x; - - x = UNSIGNED(arg, df); - - x = (x & 0x5555555555555555ULL) + ((x >> 1) & 0x5555555555555555ULL); - x = (x & 0x3333333333333333ULL) + ((x >> 2) & 0x3333333333333333ULL); - x = (x & 0x0F0F0F0F0F0F0F0FULL) + ((x >> 4) & 0x0F0F0F0F0F0F0F0FULL); - x = (x & 0x00FF00FF00FF00FFULL) + ((x >> 8) & 0x00FF00FF00FF00FFULL); - x = (x & 0x0000FFFF0000FFFFULL) + ((x >> 16) & 0x0000FFFF0000FFFFULL); - x = (x & 0x00000000FFFFFFFFULL) + ((x >> 32)); - - return x; -} - -static inline int64_t msa_nlzc_df(uint32_t df, int64_t arg) -{ - uint64_t x, y; - int n, c; - - x = UNSIGNED(arg, df); - n = DF_BITS(df); - c = DF_BITS(df) / 2; - - do { - y = x >> c; - if (y != 0) { - n = n - c; - x = y; - } - c = c >> 1; - } while (c != 0); - - return n - x; -} - -static inline int64_t msa_nloc_df(uint32_t df, int64_t arg) -{ - return msa_nlzc_df(df, UNSIGNED((~arg), df)); -} - void helper_msa_fill_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t rs) { @@ -2582,61 +3908,6 @@ void helper_msa_fill_df(CPUMIPSState *env, uint32_t df, uint32_t wd, } } -#define MSA_UNOP_DF(func) \ -void helper_msa_ ## func ## _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); \ - \ - switch (df) { \ - case DF_BYTE: \ - 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: \ - 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: \ - 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: \ - pwd->d[0] = msa_ ## func ## _df(df, pws->d[0]); \ - pwd->d[1] = msa_ ## func ## _df(df, pws->d[1]); \ - break; \ - default: \ - assert(0); \ - } \ -} - -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) diff --git a/target/mips/translate.c b/target/mips/translate.c index f2119955cf69ba0953f5ae478b4d37159dafb269..50397167fca7277e03747a6fb5dc09594281d92a 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -7118,7 +7118,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) tcg_gen_andi_tl(arg, arg, ~0xffff); register_name = "BadInstrX"; break; - default: + default: goto cp0_unimplemented; } break; @@ -7545,7 +7545,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) case CP0_REG31__KSCRATCH6: CP0_CHECK(ctx->kscrexist & (1 << sel)); tcg_gen_ld_tl(arg, cpu_env, - offsetof(CPUMIPSState, CP0_KScratch[sel-2])); + offsetof(CPUMIPSState, CP0_KScratch[sel - 2])); tcg_gen_ext32s_tl(arg, arg); register_name = "KScratch"; break; @@ -8295,7 +8295,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case CP0_REG31__KSCRATCH6: CP0_CHECK(ctx->kscrexist & (1 << sel)); tcg_gen_st_tl(arg, cpu_env, - offsetof(CPUMIPSState, CP0_KScratch[sel-2])); + offsetof(CPUMIPSState, CP0_KScratch[sel - 2])); register_name = "KScratch"; break; default: @@ -8387,17 +8387,20 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) break; case CP0_REG01__YQMASK: CP0_CHECK(ctx->insn_flags & ASE_MT); - tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask)); + tcg_gen_ld_tl(arg, cpu_env, + offsetof(CPUMIPSState, CP0_YQMask)); register_name = "YQMask"; break; case CP0_REG01__VPESCHEDULE: CP0_CHECK(ctx->insn_flags & ASE_MT); - tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule)); + tcg_gen_ld_tl(arg, cpu_env, + offsetof(CPUMIPSState, CP0_VPESchedule)); register_name = "VPESchedule"; break; case CP0_REG01__VPESCHEFBACK: CP0_CHECK(ctx->insn_flags & ASE_MT); - tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack)); + tcg_gen_ld_tl(arg, cpu_env, + offsetof(CPUMIPSState, CP0_VPEScheFBack)); register_name = "VPEScheFBack"; break; case CP0_REG01__VPEOPT: @@ -8412,7 +8415,8 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) case CP0_REGISTER_02: switch (sel) { case CP0_REG02__ENTRYLO0: - tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0)); + tcg_gen_ld_tl(arg, cpu_env, + offsetof(CPUMIPSState, CP0_EntryLo0)); register_name = "EntryLo0"; break; case CP0_REG02__TCSTATUS: @@ -8756,7 +8760,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5)); register_name = "Config5"; break; - /* 6,7 are implementation dependent */ + /* 6,7 are implementation dependent */ case CP0_REG16__CONFIG6: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6)); register_name = "Config6"; @@ -8837,7 +8841,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) } break; case CP0_REGISTER_21: - /* Officially reserved, but sel 0 is used for R1x000 framemask */ + /* Officially reserved, but sel 0 is used for R1x000 framemask */ CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6)); switch (sel) { case 0: @@ -9022,7 +9026,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) case CP0_REG31__KSCRATCH6: CP0_CHECK(ctx->kscrexist & (1 << sel)); tcg_gen_ld_tl(arg, cpu_env, - offsetof(CPUMIPSState, CP0_KScratch[sel-2])); + offsetof(CPUMIPSState, CP0_KScratch[sel - 2])); register_name = "KScratch"; break; default: @@ -9112,12 +9116,14 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) break; case CP0_REG01__VPESCHEDULE: CP0_CHECK(ctx->insn_flags & ASE_MT); - tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule)); + tcg_gen_st_tl(arg, cpu_env, + offsetof(CPUMIPSState, CP0_VPESchedule)); register_name = "VPESchedule"; break; case CP0_REG01__VPESCHEFBACK: CP0_CHECK(ctx->insn_flags & ASE_MT); - tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack)); + tcg_gen_st_tl(arg, cpu_env, + offsetof(CPUMIPSState, CP0_VPEScheFBack)); register_name = "VPEScheFBack"; break; case CP0_REG01__VPEOPT: @@ -28380,15 +28386,300 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx) TCGv_i32 twt = tcg_const_i32(wt); switch (MASK_MSA_3R(ctx->opcode)) { + case OPC_BINSL_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_binsl_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_binsl_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_binsl_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_binsl_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_BINSR_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_binsr_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_binsr_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_binsr_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_binsr_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_BCLR_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_bclr_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_bclr_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_bclr_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_bclr_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_BNEG_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_bneg_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_bneg_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_bneg_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_bneg_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_BSET_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_bset_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_bset_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_bset_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_bset_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_AVE_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_AVE_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_AVER_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_AVER_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_CEQ_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_ceq_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_ceq_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_ceq_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_ceq_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_CLE_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_CLE_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_CLT_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_CLT_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_DIV_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_div_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_div_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_div_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_div_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_DIV_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_div_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_div_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_div_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_div_u_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MOD_S_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MOD_U_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt); + break; + } + break; case OPC_SLL_df: gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt); break; case OPC_ADDV_df: gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_CEQ_df: - gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_ADD_A_df: gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt); break; @@ -28431,9 +28722,6 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx) case OPC_MAX_S_df: gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_CLT_S_df: - gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_ADDS_S_df: gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt); break; @@ -28449,15 +28737,9 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx) case OPC_SRLR_df: gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_BCLR_df: - gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_MAX_U_df: gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_CLT_U_df: - gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_ADDS_U_df: gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt); break; @@ -28467,75 +28749,33 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx) case OPC_PCKOD_df: gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_BSET_df: - gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_MIN_S_df: gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_CLE_S_df: - gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_AVE_S_df: - gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_ASUB_S_df: gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_DIV_S_df: - gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_ILVL_df: gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_BNEG_df: - gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_MIN_U_df: gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_CLE_U_df: - gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_AVE_U_df: - gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_ASUB_U_df: gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_DIV_U_df: - gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_ILVR_df: gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_BINSL_df: - gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_MAX_A_df: gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_AVER_S_df: - gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_MOD_S_df: - gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_ILVEV_df: gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_BINSR_df: - gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_MIN_A_df: gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt); break; - case OPC_AVER_U_df: - gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_MOD_U_df: - gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt); - break; case OPC_ILVOD_df: gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt); break; @@ -28952,14 +29192,53 @@ static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx) #endif gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */ break; - case OPC_PCNT_df: - gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws); - break; case OPC_NLOC_df: - gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws); + switch (df) { + case DF_BYTE: + gen_helper_msa_nloc_b(cpu_env, twd, tws); + break; + case DF_HALF: + gen_helper_msa_nloc_h(cpu_env, twd, tws); + break; + case DF_WORD: + gen_helper_msa_nloc_w(cpu_env, twd, tws); + break; + case DF_DOUBLE: + gen_helper_msa_nloc_d(cpu_env, twd, tws); + break; + } break; case OPC_NLZC_df: - gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws); + switch (df) { + case DF_BYTE: + gen_helper_msa_nlzc_b(cpu_env, twd, tws); + break; + case DF_HALF: + gen_helper_msa_nlzc_h(cpu_env, twd, tws); + break; + case DF_WORD: + gen_helper_msa_nlzc_w(cpu_env, twd, tws); + break; + case DF_DOUBLE: + gen_helper_msa_nlzc_d(cpu_env, twd, tws); + break; + } + break; + case OPC_PCNT_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_pcnt_b(cpu_env, twd, tws); + break; + case DF_HALF: + gen_helper_msa_pcnt_h(cpu_env, twd, tws); + break; + case DF_WORD: + gen_helper_msa_pcnt_w(cpu_env, twd, tws); + break; + case DF_DOUBLE: + gen_helper_msa_pcnt_d(cpu_env, twd, tws); + break; + } break; default: MIPS_INVAL("MSA instruction");