diff mbox series

[RFC,17/30] target/arm/translate-a64.c: add FP16 FMULX

Message ID 20171013162438.32458-18-alex.bennee@linaro.org
State New
Headers show
Series v8.2 half-precision support (work-in-progress) | expand

Commit Message

Alex Bennée Oct. 13, 2017, 4:24 p.m. UTC
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
 target/arm/helper-a64.c    | 18 ++++++++++++++++++
 target/arm/helper-a64.h    |  1 +
 target/arm/translate-a64.c | 45 +++++++++++++++++++++++++++++++++++----------
 3 files changed, 54 insertions(+), 10 deletions(-)

-- 
2.14.1

Comments

Richard Henderson Oct. 16, 2017, 10:24 p.m. UTC | #1
On 10/13/2017 09:24 AM, Alex Bennée wrote:
> --- a/target/arm/translate-a64.c

> +++ b/target/arm/translate-a64.c

> @@ -10648,7 +10648,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)

>          }

>          /* fall through */

>      case 0x9: /* FMUL, FMULX */

> -        if (!extract32(size, 1, 1)) {

> +        if (!extract32(size, 1, 1) && !arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {

>              unallocated_encoding(s);

>              return;

>          }


This isn't quite right --

  00 = fp16
  10 = fp32
  11 = fp64

You still need to diagnose 01.

> @@ -10805,10 +10817,23 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)

>                  gen_helper_vfp_muladds(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);

>                  break;

>              case 0x9: /* FMUL, FMULX */

> -                if (u) {

> -                    gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);

> -                } else {

> -                    gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);

> +                switch (size) {

> +                case 1:


MO_* here, since you converted to them above.


r~
diff mbox series

Patch

diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 8ef15c4c45..dd26675d5c 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -559,3 +559,21 @@  ADVSIMD_HALFOP(min)
 ADVSIMD_HALFOP(max)
 ADVSIMD_HALFOP(minnum)
 ADVSIMD_HALFOP(maxnum)
+
+/* Data processing - scalar floating-point and advanced SIMD */
+
+float16 HELPER(advsimd_mulxh)(float16 a, float16 b, void *fpstp)
+{
+    float_status *fpst = fpstp;
+
+    a = float16_squash_input_denormal(a, fpst);
+    b = float16_squash_input_denormal(b, fpst);
+
+    if ((float16_is_zero(a) && float16_is_infinity(b)) ||
+        (float16_is_infinity(a) && float16_is_zero(b))) {
+        /* 2.0 with the sign bit set to sign(A) XOR sign(B) */
+        return make_float16((1U << 14) |
+                            ((float16_val(a) ^ float16_val(b)) & (1U << 15)));
+    }
+    return float16_mul(a, b, fpst);
+}
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
index a4ce87970e..0f97eb607f 100644
--- a/target/arm/helper-a64.h
+++ b/target/arm/helper-a64.h
@@ -52,3 +52,4 @@  DEF_HELPER_3(advsimd_maxh, f16, f16, f16, ptr)
 DEF_HELPER_3(advsimd_minh, f16, f16, f16, ptr)
 DEF_HELPER_3(advsimd_maxnumh, f16, f16, f16, ptr)
 DEF_HELPER_3(advsimd_minnumh, f16, f16, f16, ptr)
+DEF_HELPER_3(advsimd_mulxh, f16, f16, f16, ptr)
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index f687bab214..d12106695f 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -10648,7 +10648,7 @@  static void disas_simd_indexed(DisasContext *s, uint32_t insn)
         }
         /* fall through */
     case 0x9: /* FMUL, FMULX */
-        if (!extract32(size, 1, 1)) {
+        if (!extract32(size, 1, 1) && !arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
             unallocated_encoding(s);
             return;
         }
@@ -10660,18 +10660,30 @@  static void disas_simd_indexed(DisasContext *s, uint32_t insn)
     }
 
     if (is_fp) {
-        /* low bit of size indicates single/double */
-        size = extract32(size, 0, 1) ? 3 : 2;
-        if (size == 2) {
+        /* convert insn encoded size to TCGMemOp size */
+        switch (size) {
+        case 0: /* half-precision */
+            size = MO_16;
+            index = h << 2 | l << 1 | m;
+            break;
+        case 2: /* single precision */
+            size = MO_32;
             index = h << 1 | l;
-        } else {
+            rm |= (m << 4);
+            break;
+        case 3: /* double precision */
+            size = MO_64;
             if (l || !is_q) {
                 unallocated_encoding(s);
                 return;
             }
             index = h;
+            rm |= (m << 4);
+            break;
+        default:
+            g_assert_not_reached();
+            break;
         }
-        rm |= (m << 4);
     } else {
         switch (size) {
         case 1:
@@ -10805,10 +10817,23 @@  static void disas_simd_indexed(DisasContext *s, uint32_t insn)
                 gen_helper_vfp_muladds(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
                 break;
             case 0x9: /* FMUL, FMULX */
-                if (u) {
-                    gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
-                } else {
-                    gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
+                switch (size) {
+                case 1:
+                    if (u) {
+                        gen_helper_advsimd_mulxh(tcg_res, tcg_op, tcg_idx, fpst);
+                    } else {
+                        g_assert_not_reached();
+                    }
+                    break;
+                case 2:
+                    if (u) {
+                        gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
+                    } else {
+                        gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
+                    }
+                    break;
+                default:
+                    g_assert_not_reached();
                 }
                 break;
             case 0xc: /* SQDMULH */