diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index 40dbd2d4..8fc57b31 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -768,25 +768,6 @@ static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v) tcg_temp_free_i64(tcg_ctx, tmp); } -TCGv_ptr get_fpstatus_ptr(TCGContext *tcg_ctx, bool is_f16) -{ - TCGv_ptr statusptr = tcg_temp_new_ptr(tcg_ctx); - int offset; - - /* In A64 all instructions (both FP and Neon) use the FPCR; there - * is no equivalent of the A32 Neon "standard FPSCR value". - * However half-precision operations operate under a different - * FZ16 flag and use vfp.fp_status_f16 instead of vfp.fp_status. - */ - if (is_f16) { - offset = offsetof(CPUARMState, vfp.fp_status_f16); - } else { - offset = offsetof(CPUARMState, vfp.fp_status); - } - tcg_gen_addi_ptr(tcg_ctx, statusptr, tcg_ctx->cpu_env, offset); - return statusptr; -} - /* Expand a 2-operand AdvSIMD vector operation using an expander function. */ static void gen_gvec_fn2(DisasContext *s, bool is_q, int rd, int rn, GVecGen2Fn *gvec_fn, int vece) @@ -862,7 +843,7 @@ static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn, { TCGContext *tcg_ctx = s->uc->tcg_ctx; - TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, is_fp16); + TCGv_ptr fpst = fpstatus_ptr(tcg_ctx, is_fp16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(tcg_ctx, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn), vec_full_reg_offset(s, rm), fpst, @@ -6135,7 +6116,7 @@ static void handle_fp_compare(DisasContext *s, int size, { TCGContext *tcg_ctx = s->uc->tcg_ctx; TCGv_i64 tcg_flags = tcg_temp_new_i64(tcg_ctx); - TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, size == MO_16); + TCGv_ptr fpst = fpstatus_ptr(tcg_ctx, size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); if (size == MO_64) { TCGv_i64 tcg_vn, tcg_vm; @@ -6397,7 +6378,7 @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn) tcg_gen_xori_i32(tcg_ctx, tcg_res, tcg_op, 0x8000); break; case 0x3: /* FSQRT */ - fpst = get_fpstatus_ptr(tcg_ctx, true); + fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR_F16); gen_helper_sqrt_f16(tcg_ctx, tcg_res, tcg_op, fpst); break; case 0x8: /* FRINTN */ @@ -6407,7 +6388,7 @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn) case 0xc: /* FRINTA */ { TCGv_i32 tcg_rmode = tcg_const_i32(tcg_ctx, arm_rmode_to_sf(opcode & 7)); - fpst = get_fpstatus_ptr(tcg_ctx, true); + fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR_F16); gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); gen_helper_advsimd_rinth(tcg_ctx, tcg_res, tcg_op, fpst); @@ -6417,11 +6398,11 @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn) break; } case 0xe: /* FRINTX */ - fpst = get_fpstatus_ptr(tcg_ctx, true); + fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR_F16); gen_helper_advsimd_rinth_exact(tcg_ctx, tcg_res, tcg_op, fpst); break; case 0xf: /* FRINTI */ - fpst = get_fpstatus_ptr(tcg_ctx, true); + fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR_F16); gen_helper_advsimd_rinth(tcg_ctx, tcg_res, tcg_op, fpst); break; default: @@ -6494,7 +6475,7 @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn) g_assert_not_reached(); } - fpst = get_fpstatus_ptr(tcg_ctx, false); + fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); if (rmode >= 0) { TCGv_i32 tcg_rmode = tcg_const_i32(tcg_ctx, rmode); gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); @@ -6572,7 +6553,7 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn) g_assert_not_reached(); } - fpst = get_fpstatus_ptr(tcg_ctx, false); + fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); if (rmode >= 0) { TCGv_i32 tcg_rmode = tcg_const_i32(tcg_ctx, rmode); gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); @@ -6609,7 +6590,7 @@ static void handle_fp_fcvt(DisasContext *s, int opcode, /* Single to half */ TCGv_i32 tcg_rd = tcg_temp_new_i32(tcg_ctx); TCGv_i32 ahp = get_ahp_flag(s); - TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, false); + TCGv_ptr fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); gen_helper_vfp_fcvt_f32_to_f16(tcg_ctx, tcg_rd, tcg_rn, fpst, ahp); /* write_fp_sreg is OK here because top half of tcg_rd is zero */ @@ -6629,7 +6610,7 @@ static void handle_fp_fcvt(DisasContext *s, int opcode, /* Double to single */ gen_helper_vfp_fcvtsd(tcg_ctx, tcg_rd, tcg_rn, tcg_ctx->cpu_env); } else { - TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, false); + TCGv_ptr fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); TCGv_i32 ahp = get_ahp_flag(s); /* Double to half */ gen_helper_vfp_fcvt_f64_to_f16(tcg_ctx, tcg_rd, tcg_rn, fpst, ahp); @@ -6645,7 +6626,7 @@ static void handle_fp_fcvt(DisasContext *s, int opcode, case 0x3: { TCGv_i32 tcg_rn = read_fp_sreg(s, rn); - TCGv_ptr tcg_fpst = get_fpstatus_ptr(tcg_ctx, false); + TCGv_ptr tcg_fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); TCGv_i32 tcg_ahp = get_ahp_flag(s); tcg_gen_ext16u_i32(tcg_ctx, tcg_rn, tcg_rn); if (dtype == 0) { @@ -6763,7 +6744,7 @@ static void handle_fp_2src_single(DisasContext *s, int opcode, TCGv_ptr fpst; tcg_res = tcg_temp_new_i32(tcg_ctx); - fpst = get_fpstatus_ptr(tcg_ctx, false); + fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); tcg_op1 = read_fp_sreg(s, rn); tcg_op2 = read_fp_sreg(s, rm); @@ -6817,7 +6798,7 @@ static void handle_fp_2src_double(DisasContext *s, int opcode, TCGv_ptr fpst; tcg_res = tcg_temp_new_i64(tcg_ctx); - fpst = get_fpstatus_ptr(tcg_ctx, false); + fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); tcg_op1 = read_fp_dreg(s, rn); tcg_op2 = read_fp_dreg(s, rm); @@ -6872,7 +6853,7 @@ static void handle_fp_2src_half(DisasContext *s, int opcode, TCGv_ptr fpst; tcg_res = tcg_temp_new_i32(tcg_ctx); - fpst = get_fpstatus_ptr(tcg_ctx, true); + fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR_F16); tcg_op1 = read_fp_hreg(s, rn); tcg_op2 = read_fp_hreg(s, rm); @@ -6972,7 +6953,7 @@ static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1, TCGContext *tcg_ctx = s->uc->tcg_ctx; TCGv_i32 tcg_op1, tcg_op2, tcg_op3; TCGv_i32 tcg_res = tcg_temp_new_i32(tcg_ctx); - TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, false); + TCGv_ptr fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); tcg_op1 = read_fp_sreg(s, rn); tcg_op2 = read_fp_sreg(s, rm); @@ -7011,7 +6992,7 @@ static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1, TCGContext *tcg_ctx = s->uc->tcg_ctx; TCGv_i64 tcg_op1, tcg_op2, tcg_op3; TCGv_i64 tcg_res = tcg_temp_new_i64(tcg_ctx); - TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, false); + TCGv_ptr fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); tcg_op1 = read_fp_dreg(s, rn); tcg_op2 = read_fp_dreg(s, rm); @@ -7051,7 +7032,7 @@ static void handle_fp_3src_half(DisasContext *s, bool o0, bool o1, TCGv_i32 tcg_op1, tcg_op2, tcg_op3; TCGv_i32 tcg_res = tcg_temp_new_i32(tcg_ctx); - TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, true); + TCGv_ptr fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR_F16); tcg_op1 = read_fp_hreg(s, rn); tcg_op2 = read_fp_hreg(s, rm); @@ -7199,7 +7180,7 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode, TCGv_i32 tcg_shift, tcg_single; TCGv_i64 tcg_double; - tcg_fpstatus = get_fpstatus_ptr(tcg_ctx, type == 3); + tcg_fpstatus = fpstatus_ptr(tcg_ctx, type == 3 ? FPST_FPCR_F16 : FPST_FPCR); tcg_shift = tcg_const_i32(tcg_ctx, 64 - scale); @@ -7489,7 +7470,7 @@ static void handle_fjcvtzs(DisasContext *s, int rd, int rn) { TCGContext *tcg_ctx = s->uc->tcg_ctx; TCGv_i64 t = read_fp_dreg(s, rn); - TCGv_ptr fpstatus = get_fpstatus_ptr(tcg_ctx, false); + TCGv_ptr fpstatus = fpstatus_ptr(tcg_ctx, FPST_FPCR); gen_helper_fjcvtzs(tcg_ctx, t, t, fpstatus); @@ -8109,7 +8090,7 @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn) * Note that correct NaN propagation requires that we do these * operations in exactly the order specified by the pseudocode. */ - TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, size == MO_16); + TCGv_ptr fpst = fpstatus_ptr(tcg_ctx, size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); int fpopcode = opcode | is_min << 4 | is_u << 5; int vmap = (1 << elements) - 1; TCGv_i32 tcg_res32 = do_reduction_op(s, fpopcode, rn, esize, @@ -8628,7 +8609,7 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn) return; } - fpst = get_fpstatus_ptr(tcg_ctx, size == MO_16); + fpst = fpstatus_ptr(tcg_ctx, size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); break; default: unallocated_encoding(s); @@ -9147,7 +9128,7 @@ static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn, int fracbits, int size) { TCGContext *tcg_ctx = s->uc->tcg_ctx; - TCGv_ptr tcg_fpst = get_fpstatus_ptr(tcg_ctx, size == MO_16); + TCGv_ptr tcg_fpst = fpstatus_ptr(tcg_ctx, size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); TCGv_i32 tcg_shift = NULL; MemOp mop = size | (is_signed ? MO_SIGN : 0); @@ -9329,7 +9310,7 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar, assert(!(is_scalar && is_q)); tcg_rmode = tcg_const_i32(tcg_ctx, arm_rmode_to_sf(FPROUNDING_ZERO)); - tcg_fpstatus = get_fpstatus_ptr(tcg_ctx, size == MO_16); + tcg_fpstatus = fpstatus_ptr(tcg_ctx, size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, tcg_fpstatus); fracbits = (16 << size) - immhb; tcg_shift = tcg_const_i32(tcg_ctx, fracbits); @@ -9671,7 +9652,7 @@ static void handle_3same_float(DisasContext *s, int size, int elements, { TCGContext *tcg_ctx = s->uc->tcg_ctx; int pass; - TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, false); + TCGv_ptr fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); for (pass = 0; pass < elements; pass++) { if (size) { @@ -10066,7 +10047,7 @@ static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s, return; } - fpst = get_fpstatus_ptr(tcg_ctx, true); + fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR_F16); tcg_op1 = read_fp_hreg(s, rn); tcg_op2 = read_fp_hreg(s, rm); @@ -10322,7 +10303,7 @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode, return; } - fpst = get_fpstatus_ptr(tcg_ctx, size == MO_16); + fpst = fpstatus_ptr(tcg_ctx, size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); if (is_double) { TCGv_i64 tcg_op = tcg_temp_new_i64(tcg_ctx); @@ -10453,7 +10434,7 @@ static void handle_2misc_reciprocal(DisasContext *s, int opcode, { TCGContext *tcg_ctx = s->uc->tcg_ctx; bool is_double = (size == 3); - TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, false); + TCGv_ptr fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); if (is_double) { TCGv_i64 tcg_op = tcg_temp_new_i64(tcg_ctx); @@ -10595,7 +10576,7 @@ static void handle_2misc_narrow(DisasContext *s, bool scalar, } else { TCGv_i32 tcg_lo = tcg_temp_new_i32(tcg_ctx); TCGv_i32 tcg_hi = tcg_temp_new_i32(tcg_ctx); - TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, false); + TCGv_ptr fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); TCGv_i32 ahp = get_ahp_flag(s); tcg_gen_extr_i64_i32(tcg_ctx, tcg_lo, tcg_hi, tcg_op); @@ -10859,7 +10840,7 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn) if (is_fcvt) { tcg_rmode = tcg_const_i32(tcg_ctx, arm_rmode_to_sf(rmode)); - tcg_fpstatus = get_fpstatus_ptr(tcg_ctx, false); + tcg_fpstatus = fpstatus_ptr(tcg_ctx, FPST_FPCR); gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, tcg_fpstatus); } else { tcg_rmode = NULL; @@ -11691,7 +11672,7 @@ static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode, /* Floating point operations need fpst */ if (opcode >= 0x58) { - fpst = get_fpstatus_ptr(tcg_ctx, false); + fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); } else { fpst = NULL; } @@ -12296,7 +12277,7 @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn) break; } - fpst = get_fpstatus_ptr(tcg_ctx, true); + fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR_F16); if (pairwise) { int maxpass = is_q ? 8 : 4; @@ -12589,7 +12570,7 @@ static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q, /* 16 -> 32 bit fp conversion */ int srcelt = is_q ? 4 : 0; TCGv_i32 tcg_res[4]; - TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, false); + TCGv_ptr fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR); TCGv_i32 ahp = get_ahp_flag(s); for (pass = 0; pass < 4; pass++) { @@ -13066,7 +13047,7 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) } if (need_fpstatus || need_rmode) { - tcg_fpstatus = get_fpstatus_ptr(tcg_ctx, false); + tcg_fpstatus = fpstatus_ptr(tcg_ctx, FPST_FPCR); } else { tcg_fpstatus = NULL; } @@ -13457,7 +13438,7 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn) } if (need_rmode || need_fpst) { - tcg_fpstatus = get_fpstatus_ptr(tcg_ctx, true); + tcg_fpstatus = fpstatus_ptr(tcg_ctx, FPST_FPCR_F16); } if (need_rmode) { @@ -13767,7 +13748,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn) } if (is_fp) { - fpst = get_fpstatus_ptr(tcg_ctx, is_fp16); + fpst = fpstatus_ptr(tcg_ctx, is_fp16 ? FPST_FPCR_F16 : FPST_FPCR); } else { fpst = NULL; } diff --git a/qemu/target/arm/translate-a64.h b/qemu/target/arm/translate-a64.h index be6b9000..61be6978 100644 --- a/qemu/target/arm/translate-a64.h +++ b/qemu/target/arm/translate-a64.h @@ -37,7 +37,6 @@ TCGv_i64 cpu_reg_sp(DisasContext *s, int reg); TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf); TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf); void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v); -TCGv_ptr get_fpstatus_ptr(TCGContext *, bool); bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn, unsigned int imms, unsigned int immr); bool sve_access_check(DisasContext *s); diff --git a/qemu/target/arm/translate-sve.c b/qemu/target/arm/translate-sve.c index f729efb2..7984643c 100644 --- a/qemu/target/arm/translate-sve.c +++ b/qemu/target/arm/translate-sve.c @@ -3598,7 +3598,7 @@ static bool trans_FMLA_zzxz(DisasContext *s, arg_FMLA_zzxz *a) if (sve_access_check(s)) { TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_4_ptr(tcg_ctx, vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -3625,7 +3625,7 @@ static bool trans_FMUL_zzx(DisasContext *s, arg_FMUL_zzx *a) if (sve_access_check(s)) { TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(tcg_ctx, vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -3658,7 +3658,7 @@ static void do_reduce(DisasContext *s, arg_rpr_esz *a, tcg_gen_addi_ptr(tcg_ctx, t_zn, tcg_ctx->cpu_env, vec_full_reg_offset(s, a->rn)); tcg_gen_addi_ptr(tcg_ctx, t_pg, tcg_ctx->cpu_env, pred_full_reg_offset(s, a->pg)); - status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); fn(tcg_ctx, temp, t_zn, t_pg, status, t_desc); tcg_temp_free_ptr(tcg_ctx, t_zn); @@ -3701,7 +3701,7 @@ static void do_zz_fp(DisasContext *s, arg_rr_esz *a, gen_helper_gvec_2_ptr *fn) { TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_2_ptr(tcg_ctx, vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), @@ -3750,7 +3750,7 @@ static void do_ppz_fp(DisasContext *s, arg_rpr_esz *a, { TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(tcg_ctx, pred_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), @@ -3803,7 +3803,7 @@ static bool trans_FTMAD(DisasContext *s, arg_FTMAD *a) if (sve_access_check(s)) { TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(tcg_ctx, vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -3844,7 +3844,7 @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a) t_pg = tcg_temp_new_ptr(tcg_ctx); tcg_gen_addi_ptr(tcg_ctx, t_rm, tcg_ctx->cpu_env, vec_full_reg_offset(s, a->rm)); tcg_gen_addi_ptr(tcg_ctx, t_pg, tcg_ctx->cpu_env, pred_full_reg_offset(s, a->pg)); - t_fpst = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + t_fpst = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); t_desc = tcg_const_i32(tcg_ctx, simd_desc(vsz, vsz, 0)); fns[a->esz - 1](tcg_ctx, t_val, t_val, t_rm, t_pg, t_fpst, t_desc); @@ -3872,7 +3872,7 @@ static bool do_zzz_fp(DisasContext *s, arg_rrr_esz *a, if (sve_access_check(s)) { TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(tcg_ctx, vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -3915,7 +3915,7 @@ static bool do_zpzz_fp(DisasContext *s, arg_rprr_esz *a, if (sve_access_check(s)) { TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_4_ptr(tcg_ctx, vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -3968,7 +3968,7 @@ static void do_fp_scalar(DisasContext *s, int zd, int zn, int pg, bool is_fp16, tcg_gen_addi_ptr(tcg_ctx, t_zn, tcg_ctx->cpu_env, vec_full_reg_offset(s, zn)); tcg_gen_addi_ptr(tcg_ctx, t_pg, tcg_ctx->cpu_env, pred_full_reg_offset(s, pg)); - status = get_fpstatus_ptr(tcg_ctx, is_fp16); + status = fpstatus_ptr(tcg_ctx, is_fp16 ? FPST_FPCR_F16 : FPST_FPCR); desc = tcg_const_i32(tcg_ctx, simd_desc(vsz, vsz, 0)); fn(tcg_ctx, t_zd, t_zn, t_pg, scalar, status, desc); @@ -4034,7 +4034,7 @@ static bool do_fp_cmp(DisasContext *s, arg_rprr_esz *a, if (sve_access_check(s)) { TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_4_ptr(tcg_ctx, pred_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -4079,7 +4079,7 @@ static bool trans_FCADD(DisasContext *s, arg_FCADD *a) if (sve_access_check(s)) { TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_4_ptr(tcg_ctx, vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -4100,7 +4100,7 @@ static bool do_fmla(DisasContext *s, arg_rprrr_esz *a, if (sve_access_check(s)) { TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_5_ptr(tcg_ctx, vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -4145,7 +4145,7 @@ static bool trans_FCMLA_zpzzz(DisasContext *s, arg_FCMLA_zpzzz *a) if (sve_access_check(s)) { TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_5_ptr(tcg_ctx, vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -4169,7 +4169,7 @@ static bool trans_FCMLA_zzxz(DisasContext *s, arg_FCMLA_zzxz *a) if (sve_access_check(s)) { TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(tcg_ctx, vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -4191,7 +4191,7 @@ static bool do_zpz_ptr(DisasContext *s, int rd, int rn, int pg, if (sve_access_check(s)) { TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, is_fp16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, is_fp16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(tcg_ctx, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn), pred_full_reg_offset(s, pg), @@ -4338,7 +4338,7 @@ static bool do_frint_mode(DisasContext *s, arg_rpr_esz *a, int mode) TCGContext *tcg_ctx = s->uc->tcg_ctx; unsigned vsz = vec_full_reg_size(s); TCGv_i32 tmode = tcg_const_i32(tcg_ctx, mode); - TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(tcg_ctx, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); gen_helper_set_rmode(tcg_ctx, tmode, tmode, status); diff --git a/qemu/target/arm/translate.h b/qemu/target/arm/translate.h index 8e05d05f..fcd066f8 100644 --- a/qemu/target/arm/translate.h +++ b/qemu/target/arm/translate.h @@ -401,4 +401,55 @@ typedef void CryptoThreeOpIntFn(TCGContext *, TCGv_ptr, TCGv_ptr, TCGv_i32); typedef void CryptoThreeOpFn(TCGContext *, TCGv_ptr, TCGv_ptr, TCGv_ptr); typedef void AtomicThreeOpFn(TCGContext *, TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, MemOp); +/* + * Enum for argument to fpstatus_ptr(). + */ +typedef enum ARMFPStatusFlavour { + FPST_FPCR, + FPST_FPCR_F16, + FPST_STD, + FPST_STD_F16, +} ARMFPStatusFlavour; + +/** + * fpstatus_ptr: return TCGv_ptr to the specified fp_status field + * + * We have multiple softfloat float_status fields in the Arm CPU state struct + * (see the comment in cpu.h for details). Return a TCGv_ptr which has + * been set up to point to the requested field in the CPU state struct. + * The options are: + * + * FPST_FPCR + * for non-FP16 operations controlled by the FPCR + * FPST_FPCR_F16 + * for operations controlled by the FPCR where FPCR.FZ16 is to be used + * FPST_STD + * for A32/T32 Neon operations using the "standard FPSCR value" + * FPST_STD_F16 + * as FPST_STD, but where FPCR.FZ16 is to be used + */ +static inline TCGv_ptr fpstatus_ptr(TCGContext *s, ARMFPStatusFlavour flavour) +{ + TCGv_ptr statusptr = tcg_temp_new_ptr(s); + int offset; + + switch (flavour) { + case FPST_FPCR: + offset = offsetof(CPUARMState, vfp.fp_status); + break; + case FPST_FPCR_F16: + offset = offsetof(CPUARMState, vfp.fp_status_f16); + break; + case FPST_STD: + offset = offsetof(CPUARMState, vfp.standard_fp_status); + break; + case FPST_STD_F16: + /* Not yet used or implemented: fall through to assert */ + default: + g_assert_not_reached(); + } + tcg_gen_addi_ptr(s, statusptr, s->cpu_env, offset); + return statusptr; +} + #endif /* TARGET_ARM_TRANSLATE_H */