Signed-off-by: Richard Henderson <[email protected]>
---
target/arm/tcg/helper-a64-defs.h | 4 ++++
target/arm/tcg/vec_internal.h | 4 ++++
target/arm/tcg/translate-a64.c | 7 +++++++
target/arm/tcg/vec_helper64.c | 16 ++++++++++++++++
target/arm/tcg/a64.decode | 3 +++
5 files changed, 34 insertions(+)
diff --git a/target/arm/tcg/helper-a64-defs.h b/target/arm/tcg/helper-a64-defs.h
index 215df1201b..b7880f773e 100644
--- a/target/arm/tcg/helper-a64-defs.h
+++ b/target/arm/tcg/helper-a64-defs.h
@@ -152,6 +152,10 @@ DEF_HELPER_FLAGS_5(gvec_famin_s, TCG_CALL_NO_RWG, void,
ptr, ptr, ptr, fpst, i32
DEF_HELPER_FLAGS_5(gvec_famax_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst,
i32)
DEF_HELPER_FLAGS_5(gvec_famin_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst,
i32)
+DEF_HELPER_FLAGS_5(gvec_fscale_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst,
i32)
+DEF_HELPER_FLAGS_5(gvec_fscale_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst,
i32)
+DEF_HELPER_FLAGS_5(gvec_fscale_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst,
i32)
+
#ifndef CONFIG_USER_ONLY
DEF_HELPER_2(exception_return, void, env, i64)
#endif
diff --git a/target/arm/tcg/vec_internal.h b/target/arm/tcg/vec_internal.h
index cc2691b2f6..68b1116171 100644
--- a/target/arm/tcg/vec_internal.h
+++ b/target/arm/tcg/vec_internal.h
@@ -345,6 +345,10 @@ float32 float32_famin(float32, float32, float_status *);
float64 float64_famax(float64, float64, float_status *);
float64 float64_famin(float64, float64, float_status *);
+#define float16_fscale float16_scalbn
+#define float32_fscale float32_scalbn
+float64 float64_fscale(float64, int64_t, float_status *);
+
/*
* Decode helper functions for predicate as counter.
*/
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index d2a4b0fadc..ac18ceeeab 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -6496,6 +6496,13 @@ static gen_helper_gvec_3_ptr * const f_vector_famin[3] =
{
};
TRANS_FEAT(FAMIN, aa64_faminmax, do_fp3_vector, a, 0, f_vector_famin)
+static gen_helper_gvec_3_ptr * const f_vector_fscale[3] = {
+ gen_helper_gvec_fscale_h,
+ gen_helper_gvec_fscale_s,
+ gen_helper_gvec_fscale_d,
+};
+TRANS_FEAT(FSCALE, aa64_f8cvt, do_fp3_vector, a, 0, f_vector_fscale)
+
static bool do_fmlal(DisasContext *s, arg_qrrr_e *a, bool is_s, bool is_2)
{
if (fp_access_check(s)) {
diff --git a/target/arm/tcg/vec_helper64.c b/target/arm/tcg/vec_helper64.c
index 4a5b0782d1..2f481ac489 100644
--- a/target/arm/tcg/vec_helper64.c
+++ b/target/arm/tcg/vec_helper64.c
@@ -174,3 +174,19 @@ DO_3OP(gvec_famax_s, float32_famax, float32)
DO_3OP(gvec_famin_s, float32_famin, float32)
DO_3OP(gvec_famax_d, float64_famax, float64)
DO_3OP(gvec_famin_d, float64_famin, float64)
+
+float64 float64_fscale(float64 n, int64_t m, float_status *s)
+{
+ /*
+ * Given the 'int' parameter of float64_scalbn, we have to saturate
+ * the 'int64_t' parameter of the operation to some value. Since
+ * float64 has an 11-bit exponent, saturating to 12 bits is sufficient
+ * to ensure that DBL_TRUE_MIN can be made to overflow.
+ */
+ int sat_m = MIN(MAX(m, -0xfff), 0xfff);
+ return float64_scalbn(n, sat_m, s);
+}
+
+DO_3OP(gvec_fscale_h, float16_fscale, int16_t)
+DO_3OP(gvec_fscale_s, float32_fscale, int32_t)
+DO_3OP(gvec_fscale_d, float64_fscale, int64_t)
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
index 666a293540..02c7264cb9 100644
--- a/target/arm/tcg/a64.decode
+++ b/target/arm/tcg/a64.decode
@@ -1198,6 +1198,9 @@ FAMAX 0.00 1110 1.1 ..... 11011 1 ..... .....
@qrrr_sd
FAMIN 0.10 1110 110 ..... 00011 1 ..... ..... @qrrr_h
FAMIN 0.10 1110 1.1 ..... 11011 1 ..... ..... @qrrr_sd
+FSCALE 0.10 1110 110 ..... 00111 1 ..... ..... @qrrr_h
+FSCALE 0.10 1110 1.1 ..... 11111 1 ..... ..... @qrrr_sd
+
### Advanced SIMD scalar x indexed element
FMUL_si 0101 1111 00 .. .... 1001 . 0 ..... ..... @rrx_h
--
2.43.0