@@ -8348,6 +8348,63 @@ static const FPScalar1Int f_scalar_fneg = {
};
TRANS(FNEG_s, do_fp1_scalar_int, a, &f_scalar_fneg)
+typedef struct FPScalar1 {
+ void (*gen_h)(TCGv_i32, TCGv_i32, TCGv_ptr);
+ void (*gen_s)(TCGv_i32, TCGv_i32, TCGv_ptr);
+ void (*gen_d)(TCGv_i64, TCGv_i64, TCGv_ptr);
+} FPScalar1;
+
+static bool do_fp1_scalar(DisasContext *s, arg_rr_e *a,
+ const FPScalar1 *f, int rmode)
+{
+ TCGv_i32 tcg_rmode = NULL;
+ TCGv_ptr fpst;
+ TCGv_i64 t64;
+ TCGv_i32 t32;
+ int check = fp_access_check_scalar_hsd(s, a->esz);
+
+ if (check <= 0) {
+ return check == 0;
+ }
+
+ fpst = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
+ if (rmode >= 0) {
+ tcg_rmode = gen_set_rmode(rmode, fpst);
+ }
+
+ switch (a->esz) {
+ case MO_64:
+ t64 = read_fp_dreg(s, a->rn);
+ f->gen_d(t64, t64, fpst);
+ write_fp_dreg(s, a->rd, t64);
+ break;
+ case MO_32:
+ t32 = read_fp_sreg(s, a->rn);
+ f->gen_s(t32, t32, fpst);
+ write_fp_sreg(s, a->rd, t32);
+ break;
+ case MO_16:
+ t32 = read_fp_hreg(s, a->rn);
+ f->gen_h(t32, t32, fpst);
+ write_fp_sreg(s, a->rd, t32);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ if (rmode >= 0) {
+ gen_restore_rmode(tcg_rmode, fpst);
+ }
+ return true;
+}
+
+static const FPScalar1 f_scalar_fsqrt = {
+ gen_helper_vfp_sqrth,
+ gen_helper_vfp_sqrts,
+ gen_helper_vfp_sqrtd,
+};
+TRANS(FSQRT_s, do_fp1_scalar, a, &f_scalar_fsqrt, -1)
+
/* Floating-point data-processing (1 source) - half precision */
static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
{
@@ -8356,10 +8413,6 @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
TCGv_i32 tcg_res = tcg_temp_new_i32();
switch (opcode) {
- case 0x3: /* FSQRT */
- fpst = fpstatus_ptr(FPST_FPCR_F16);
- gen_helper_vfp_sqrth(tcg_res, tcg_op, fpst);
- break;
case 0x8: /* FRINTN */
case 0x9: /* FRINTP */
case 0xa: /* FRINTM */
@@ -8386,6 +8439,7 @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
case 0x0: /* FMOV */
case 0x1: /* FABS */
case 0x2: /* FNEG */
+ case 0x3: /* FSQRT */
g_assert_not_reached();
}
@@ -8404,9 +8458,6 @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
tcg_res = tcg_temp_new_i32();
switch (opcode) {
- case 0x3: /* FSQRT */
- gen_fpst = gen_helper_vfp_sqrts;
- break;
case 0x6: /* BFCVT */
gen_fpst = gen_helper_bfcvt;
break;
@@ -8442,6 +8493,7 @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
case 0x0: /* FMOV */
case 0x1: /* FABS */
case 0x2: /* FNEG */
+ case 0x3: /* FSQRT */
g_assert_not_reached();
}
@@ -8469,9 +8521,6 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
tcg_res = tcg_temp_new_i64();
switch (opcode) {
- case 0x3: /* FSQRT */
- gen_fpst = gen_helper_vfp_sqrtd;
- break;
case 0x8: /* FRINTN */
case 0x9: /* FRINTP */
case 0xa: /* FRINTM */
@@ -8504,6 +8553,7 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
case 0x0: /* FMOV */
case 0x1: /* FABS */
case 0x2: /* FNEG */
+ case 0x3: /* FSQRT */
g_assert_not_reached();
}
@@ -1327,6 +1327,7 @@ FMINV_s 0110 1110 10 11000 01111 10 ..... ..... @rr_q1e2
FMOV_s 00011110 .. 1 000000 10000 ..... ..... @rr_hsd
FABS_s 00011110 .. 1 000001 10000 ..... ..... @rr_hsd
FNEG_s 00011110 .. 1 000010 10000 ..... ..... @rr_hsd
+FSQRT_s 00011110 .. 1 000011 10000 ..... ..... @rr_hsd
# Floating-point Immediate
Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/arm/tcg/translate-a64.c | 70 +++++++++++++++++++++++++++++----- target/arm/tcg/a64.decode | 1 + 2 files changed, 61 insertions(+), 10 deletions(-)