diff --git a/qemu/target/arm/neon-dp.decode b/qemu/target/arm/neon-dp.decode index cc2ee964..105cf2b2 100644 --- a/qemu/target/arm/neon-dp.decode +++ b/qemu/target/arm/neon-dp.decode @@ -485,5 +485,8 @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm VMUL_2sc 1111 001 . 1 . .. .... .... 1000 . 1 . 0 .... @2scalar VMUL_F_2sc 1111 001 . 1 . .. .... .... 1001 . 1 . 0 .... @2scalar + + VQDMULH_2sc 1111 001 . 1 . .. .... .... 1100 . 1 . 0 .... @2scalar + VQRDMULH_2sc 1111 001 . 1 . .. .... .... 1101 . 1 . 0 .... @2scalar ] } diff --git a/qemu/target/arm/translate-neon.inc.c b/qemu/target/arm/translate-neon.inc.c index b8ced2a3..daf3b5ea 100644 --- a/qemu/target/arm/translate-neon.inc.c +++ b/qemu/target/arm/translate-neon.inc.c @@ -2576,3 +2576,32 @@ static bool trans_VMLS_F_2sc(DisasContext *s, arg_2scalar *a) return do_2scalar(s, a, opfn[a->size], accfn[a->size]); } + +WRAP_ENV_FN(gen_VQDMULH_16, gen_helper_neon_qdmulh_s16) +WRAP_ENV_FN(gen_VQDMULH_32, gen_helper_neon_qdmulh_s32) +WRAP_ENV_FN(gen_VQRDMULH_16, gen_helper_neon_qrdmulh_s16) +WRAP_ENV_FN(gen_VQRDMULH_32, gen_helper_neon_qrdmulh_s32) + +static bool trans_VQDMULH_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenTwoOpFn * const opfn[] = { + NULL, + gen_VQDMULH_16, + gen_VQDMULH_32, + NULL, + }; + + return do_2scalar(s, a, opfn[a->size], NULL); +} + +static bool trans_VQRDMULH_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenTwoOpFn * const opfn[] = { + NULL, + gen_VQRDMULH_16, + gen_VQRDMULH_32, + NULL, + }; + + return do_2scalar(s, a, opfn[a->size], NULL); +} diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 563a0c75..eaa388f8 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -3079,21 +3079,6 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc) #define CPU_V001 s->V0, s->V0, s->V1 -static TCGv_i32 neon_load_scratch(DisasContext *s, int scratch) -{ - TCGContext *tcg_ctx = s->uc->tcg_ctx; - TCGv_i32 tmp = tcg_temp_new_i32(tcg_ctx); - tcg_gen_ld_i32(tcg_ctx, tmp, tcg_ctx->cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); - return tmp; -} - -static void neon_store_scratch(DisasContext *s, int scratch, TCGv_i32 var) -{ - TCGContext *tcg_ctx = s->uc->tcg_ctx; - tcg_gen_st_i32(tcg_ctx, var, tcg_ctx->cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); - tcg_temp_free_i32(tcg_ctx, var); -} - static int gen_neon_unzip(DisasContext *s, int rd, int rm, int size, int q) { TCGContext *tcg_ctx = s->uc->tcg_ctx; @@ -5310,35 +5295,10 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) case 1: /* Float VMLA scalar */ case 5: /* Floating point VMLS scalar */ case 9: /* Floating point VMUL scalar */ - return 1; /* handled by decodetree */ - case 12: /* VQDMULH scalar */ case 13: /* VQRDMULH scalar */ - if (u && ((rd | rn) & 1)) { - return 1; - } - tmp = neon_get_scalar(s, size, rm); - neon_store_scratch(s, 0, tmp); - for (pass = 0; pass < (u ? 4 : 2); pass++) { - tmp = neon_load_scratch(s, 0); - tmp2 = neon_load_reg(s, rn, pass); - if (op == 12) { - if (size == 1) { - gen_helper_neon_qdmulh_s16(tcg_ctx, tmp, tcg_ctx->cpu_env, tmp, tmp2); - } else { - gen_helper_neon_qdmulh_s32(tcg_ctx, tmp, tcg_ctx->cpu_env, tmp, tmp2); - } - } else { - if (size == 1) { - gen_helper_neon_qrdmulh_s16(tcg_ctx, tmp, tcg_ctx->cpu_env, tmp, tmp2); - } else { - gen_helper_neon_qrdmulh_s32(tcg_ctx, tmp, tcg_ctx->cpu_env, tmp, tmp2); - } - } - tcg_temp_free_i32(tcg_ctx, tmp2); - neon_store_reg(s, rd, pass, tmp); - } - break; + return 1; /* handled by decodetree */ + case 3: /* VQDMLAL scalar */ case 7: /* VQDMLSL scalar */ case 11: /* VQDMULL scalar */