diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
index 847fb52ee0..d4e81b13f0 100644
--- a/target/arm/Makefile.objs
+++ b/target/arm/Makefile.objs
@@ -6,6 +6,7 @@ obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
 obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
 obj-y += translate.o op_helper.o helper.o cpu.o
 obj-y += neon_helper.o iwmmxt_helper.o
+obj-$(TARGET_AARCH64) += advsimd_helper.o
 obj-y += gdbstub.o
 obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
 obj-y += crypto_helper.o
diff --git a/target/arm/advsimd_helper.c b/target/arm/advsimd_helper.c
new file mode 100644
index 0000000000..ec875a83bb
--- /dev/null
+++ b/target/arm/advsimd_helper.c
@@ -0,0 +1,85 @@
+/*
+ * ARM AdvancedSIMD helper functions
+ *
+ * Copyright (c) 2017 Linaro.
+ * Author: Alex Bennée <alex.bennee@linaro.org>
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * This code is specifically for AdvancedSIMD helpers rather than
+ * shared NEON helpers which are re-purposed for ARMv8. In practice
+ * these are helpers for newer features not found in older ARMs,
+ * currently half-precision float support.
+ *
+ * As such these helpers use the SoftFloat3c code. As we currently use
+ * both SoftFloat cores we copy the SoftFloat2a status bits to 3c
+ * before the operation and copy back at the end.
+ */
+#include "qemu/osdep.h"
+
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "exec/helper-proto.h"
+
+#include "fpu/softfloat3c/platform.h"
+#include "fpu/softfloat3c/softfloat.h"
+#include "fpu/softfloat3c/softfloat-internals.h"
+
+typedef struct softfloat_flags {
+    uint8_t float2a_flag;
+    uint8_t float3c_flag;
+} softfloat_flags;
+
+static softfloat_flags softfloat_mapping_table[] = {
+    { float_flag_inexact  , softfloat_flag_inexact },
+    { float_flag_underflow, softfloat_flag_underflow },
+    { float_flag_overflow , softfloat_flag_overflow },
+    { float_flag_invalid  , softfloat_flag_invalid },
+};
+/* FIXME: 2a has no infinite flag */
+
+static uint8_t sync_softfloat_flags_from_2a(float_status *flags2a)
+{
+    uint8_t flags = flags2a->float_exception_flags;
+    int i;
+    if (flags) {
+        for (i = 0; i < ARRAY_SIZE(softfloat_mapping_table); i++) {
+            struct softfloat_flags *map = &softfloat_mapping_table[i];
+            if (flags & map->float2a_flag) {
+                softfloat_raiseFlags(map->float3c_flag);
+            }
+        }
+    } else {
+        softfloat_exceptionFlags = 0;
+    }
+
+    return softfloat_exceptionFlags;
+}
+
+static void sync_softfloat_flags_to_2a(float_status *flags2a)
+{
+    int i;
+    if (softfloat_exceptionFlags) {
+        for (i = 0; i < ARRAY_SIZE(softfloat_mapping_table); i++) {
+            struct softfloat_flags *map = &softfloat_mapping_table[i];
+            if (softfloat_exceptionFlags & map->float3c_flag) {
+                float_raise(map->float2a_flag, flags2a);
+            }
+        }
+    } else {
+        flags2a->float_exception_flags = 0;
+    }
+}
+
+
+uint32_t HELPER(advsimd_acgt_f16)(uint32_t a, uint32_t b, void *fpstp)
+{
+    union ui16_f16 uA = { .ui = (a & 0x7fff) };
+    union ui16_f16 uB = { .ui = (b & 0x7fff) };
+    uint32_t r;
+
+    sync_softfloat_flags_from_2a(fpstp);
+    r = -f16_lt(uB.f, uA.f);
+    sync_softfloat_flags_to_2a(fpstp);
+    return r;
+}
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
index 6f9eaba533..48b400ca8e 100644
--- a/target/arm/helper-a64.h
+++ b/target/arm/helper-a64.h
@@ -44,3 +44,6 @@ DEF_HELPER_FLAGS_3(crc32_64, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32)
 DEF_HELPER_FLAGS_3(crc32c_64, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32)
 DEF_HELPER_FLAGS_4(paired_cmpxchg64_le, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_4(paired_cmpxchg64_be, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
+
+/* helper_advsimd.c */
+DEF_HELPER_3(advsimd_acgt_f16, i32, i32, i32, ptr)
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index c766829ff9..06da8408f6 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -9764,6 +9764,9 @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
         read_vec_element_i32(s, tcg_op2, rm, pass, MO_16);
 
         switch (fpopcode) {
+        case 0x35: /* FACGT */
+            gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
+            break;
         default:
             fprintf(stderr,"%s: insn %#04x fpop %#2x\n", __func__, insn, fpopcode);
             unsupported_encoding(s, insn);
