diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index e7ccb4e6..54affc83 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -5804,55 +5804,59 @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn) static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn) { TCGContext *tcg_ctx = s->uc->tcg_ctx; + void (*gen_fpst)(TCGContext *, TCGv_i32, TCGv_i32, TCGv_ptr); + TCGv_i32 tcg_op, tcg_res; TCGv_ptr fpst; - TCGv_i32 tcg_op; - TCGv_i32 tcg_res; + int rmode = -1; - fpst = get_fpstatus_ptr(s, false); tcg_op = read_fp_sreg(s, rn); tcg_res = tcg_temp_new_i32(tcg_ctx); switch (opcode) { case 0x0: /* FMOV */ tcg_gen_mov_i32(tcg_ctx, tcg_res, tcg_op); - break; + goto done; case 0x1: /* FABS */ gen_helper_vfp_abss(tcg_ctx, tcg_res, tcg_op); - break; + goto done; case 0x2: /* FNEG */ gen_helper_vfp_negs(tcg_ctx, tcg_res, tcg_op); - break; + goto done; case 0x3: /* FSQRT */ gen_helper_vfp_sqrts(tcg_ctx, tcg_res, tcg_op, tcg_ctx->cpu_env); - break; + goto done; case 0x8: /* FRINTN */ case 0x9: /* FRINTP */ case 0xa: /* FRINTM */ case 0xb: /* FRINTZ */ case 0xc: /* FRINTA */ - { - TCGv_i32 tcg_rmode = tcg_const_i32(tcg_ctx, arm_rmode_to_sf(opcode & 7)); - - gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); - gen_helper_rints(tcg_ctx, tcg_res, tcg_op, fpst); - - gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); - tcg_temp_free_i32(tcg_ctx, tcg_rmode); + rmode = arm_rmode_to_sf(opcode & 7); + gen_fpst = gen_helper_rints; break; - } case 0xe: /* FRINTX */ - gen_helper_rints_exact(tcg_ctx, tcg_res, tcg_op, fpst); + gen_fpst = gen_helper_rints_exact; break; case 0xf: /* FRINTI */ - gen_helper_rints(tcg_ctx, tcg_res, tcg_op, fpst); + gen_fpst = gen_helper_rints; break; default: - abort(); + g_assert_not_reached(); } - write_fp_sreg(s, rd, tcg_res); - + fpst = get_fpstatus_ptr(s, false); + if (rmode >= 0) { + TCGv_i32 tcg_rmode = tcg_const_i32(tcg_ctx, rmode); + gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); + gen_fpst(tcg_ctx, tcg_res, tcg_op, fpst); + gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); + tcg_temp_free_i32(tcg_ctx, tcg_rmode); + } else { + gen_fpst(tcg_ctx, tcg_res, tcg_op, fpst); + } tcg_temp_free_ptr(tcg_ctx, fpst); + + done: + write_fp_sreg(s, rd, tcg_res); tcg_temp_free_i32(tcg_ctx, tcg_op); tcg_temp_free_i32(tcg_ctx, tcg_res); } @@ -5861,9 +5865,10 @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn) static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn) { TCGContext *tcg_ctx = s->uc->tcg_ctx; + void (*gen_fpst)(TCGContext *, TCGv_i64, TCGv_i64, TCGv_ptr); + TCGv_i64 tcg_op, tcg_res; TCGv_ptr fpst; - TCGv_i64 tcg_op; - TCGv_i64 tcg_res; + int rmode = -1; switch (opcode) { case 0x0: /* FMOV */ @@ -5871,48 +5876,52 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn) return; } - fpst = get_fpstatus_ptr(s, false); tcg_op = read_fp_dreg(s, rn); tcg_res = tcg_temp_new_i64(tcg_ctx); switch (opcode) { case 0x1: /* FABS */ gen_helper_vfp_absd(tcg_ctx, tcg_res, tcg_op); - break; + goto done; case 0x2: /* FNEG */ gen_helper_vfp_negd(tcg_ctx, tcg_res, tcg_op); - break; + goto done; case 0x3: /* FSQRT */ gen_helper_vfp_sqrtd(tcg_ctx, tcg_res, tcg_op, tcg_ctx->cpu_env); - break; + goto done; case 0x8: /* FRINTN */ case 0x9: /* FRINTP */ case 0xa: /* FRINTM */ case 0xb: /* FRINTZ */ case 0xc: /* FRINTA */ - { - TCGv_i32 tcg_rmode = tcg_const_i32(tcg_ctx, arm_rmode_to_sf(opcode & 7)); - - gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); - gen_helper_rintd(tcg_ctx, tcg_res, tcg_op, fpst); - - gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); - tcg_temp_free_i32(tcg_ctx, tcg_rmode); + rmode = arm_rmode_to_sf(opcode & 7); + gen_fpst = gen_helper_rintd; break; - } case 0xe: /* FRINTX */ - gen_helper_rintd_exact(tcg_ctx, tcg_res, tcg_op, fpst); + gen_fpst = gen_helper_rintd_exact; break; case 0xf: /* FRINTI */ - gen_helper_rintd(tcg_ctx, tcg_res, tcg_op, fpst); + gen_fpst = gen_helper_rintd; break; default: - abort(); + g_assert_not_reached(); } - write_fp_dreg(s, rd, tcg_res); + fpst = get_fpstatus_ptr(s, false); + if (rmode >= 0) { + TCGv_i32 tcg_rmode = tcg_const_i32(tcg_ctx, rmode); + gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); + gen_fpst(tcg_ctx, tcg_res, tcg_op, fpst); + gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); + tcg_temp_free_i32(tcg_ctx, tcg_rmode); + } else { + gen_fpst(tcg_ctx, tcg_res, tcg_op, fpst); + } tcg_temp_free_ptr(tcg_ctx, fpst); + + done: + write_fp_dreg(s, rd, tcg_res); tcg_temp_free_i64(tcg_ctx, tcg_op); tcg_temp_free_i64(tcg_ctx, tcg_res); }