From 80074e47458727c09887441a6d8ffcfc554e98d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 15 May 2018 22:24:26 -0400 Subject: [PATCH] target/arm: Implement FCMP for fp16 These where missed out from the rest of the half-precision work. Backports commit 7a1929256ea1a03df12625e75ed571c60dca5bfb from qemu --- qemu/aarch64.h | 2 + qemu/aarch64eb.h | 2 + qemu/arm.h | 2 + qemu/armeb.h | 2 + qemu/header_gen.py | 2 + qemu/m68k.h | 2 + qemu/mips.h | 2 + qemu/mips64.h | 2 + qemu/mips64el.h | 2 + qemu/mipsel.h | 2 + qemu/powerpc.h | 2 + qemu/sparc.h | 2 + qemu/sparc64.h | 2 + qemu/target/arm/helper-a64.c | 10 ++++ qemu/target/arm/helper-a64.h | 2 + qemu/target/arm/translate-a64.c | 88 ++++++++++++++++++++++++++------- qemu/x86_64.h | 2 + 17 files changed, 111 insertions(+), 17 deletions(-) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index ae289dff..0486d6f4 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -1658,7 +1658,9 @@ #define helper_vfp_addd helper_vfp_addd_aarch64 #define helper_vfp_adds helper_vfp_adds_aarch64 #define helper_vfp_cmpd helper_vfp_cmpd_aarch64 +#define helper_vfp_cmph_a64 helper_vfp_cmph_a64_aarch64 #define helper_vfp_cmped helper_vfp_cmped_aarch64 +#define helper_vfp_cmpeh_a64 helper_vfp_cmpeh_a64_aarch64 #define helper_vfp_cmpes helper_vfp_cmpes_aarch64 #define helper_vfp_cmps helper_vfp_cmps_aarch64 #define helper_vfp_divd helper_vfp_divd_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index f9c16d97..22231d35 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -1658,7 +1658,9 @@ #define helper_vfp_addd helper_vfp_addd_aarch64eb #define helper_vfp_adds helper_vfp_adds_aarch64eb #define helper_vfp_cmpd helper_vfp_cmpd_aarch64eb +#define helper_vfp_cmph_a64 helper_vfp_cmph_a64_aarch64eb #define helper_vfp_cmped helper_vfp_cmped_aarch64eb +#define helper_vfp_cmpeh_a64 helper_vfp_cmpeh_a64_aarch64eb #define helper_vfp_cmpes helper_vfp_cmpes_aarch64eb #define helper_vfp_cmps helper_vfp_cmps_aarch64eb #define helper_vfp_divd helper_vfp_divd_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index bdcc413e..9d0453cf 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -1658,7 +1658,9 @@ #define helper_vfp_addd helper_vfp_addd_arm #define helper_vfp_adds helper_vfp_adds_arm #define helper_vfp_cmpd helper_vfp_cmpd_arm +#define helper_vfp_cmph_a64 helper_vfp_cmph_a64_arm #define helper_vfp_cmped helper_vfp_cmped_arm +#define helper_vfp_cmpeh_a64 helper_vfp_cmpeh_a64_arm #define helper_vfp_cmpes helper_vfp_cmpes_arm #define helper_vfp_cmps helper_vfp_cmps_arm #define helper_vfp_divd helper_vfp_divd_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 758293c0..c9dd7912 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -1658,7 +1658,9 @@ #define helper_vfp_addd helper_vfp_addd_armeb #define helper_vfp_adds helper_vfp_adds_armeb #define helper_vfp_cmpd helper_vfp_cmpd_armeb +#define helper_vfp_cmph_a64 helper_vfp_cmph_a64_armeb #define helper_vfp_cmped helper_vfp_cmped_armeb +#define helper_vfp_cmpeh_a64 helper_vfp_cmpeh_a64_armeb #define helper_vfp_cmpes helper_vfp_cmpes_armeb #define helper_vfp_cmps helper_vfp_cmps_armeb #define helper_vfp_divd helper_vfp_divd_armeb diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 412b580b..57218b24 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -1664,7 +1664,9 @@ symbols = ( 'helper_vfp_addd', 'helper_vfp_adds', 'helper_vfp_cmpd', + 'helper_vfp_cmph_a64', 'helper_vfp_cmped', + 'helper_vfp_cmpeh_a64', 'helper_vfp_cmpes', 'helper_vfp_cmps', 'helper_vfp_divd', diff --git a/qemu/m68k.h b/qemu/m68k.h index a5d0f9af..c28ca927 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -1658,7 +1658,9 @@ #define helper_vfp_addd helper_vfp_addd_m68k #define helper_vfp_adds helper_vfp_adds_m68k #define helper_vfp_cmpd helper_vfp_cmpd_m68k +#define helper_vfp_cmph_a64 helper_vfp_cmph_a64_m68k #define helper_vfp_cmped helper_vfp_cmped_m68k +#define helper_vfp_cmpeh_a64 helper_vfp_cmpeh_a64_m68k #define helper_vfp_cmpes helper_vfp_cmpes_m68k #define helper_vfp_cmps helper_vfp_cmps_m68k #define helper_vfp_divd helper_vfp_divd_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 01828691..4591dd2b 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -1658,7 +1658,9 @@ #define helper_vfp_addd helper_vfp_addd_mips #define helper_vfp_adds helper_vfp_adds_mips #define helper_vfp_cmpd helper_vfp_cmpd_mips +#define helper_vfp_cmph_a64 helper_vfp_cmph_a64_mips #define helper_vfp_cmped helper_vfp_cmped_mips +#define helper_vfp_cmpeh_a64 helper_vfp_cmpeh_a64_mips #define helper_vfp_cmpes helper_vfp_cmpes_mips #define helper_vfp_cmps helper_vfp_cmps_mips #define helper_vfp_divd helper_vfp_divd_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 95608454..1727223d 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -1658,7 +1658,9 @@ #define helper_vfp_addd helper_vfp_addd_mips64 #define helper_vfp_adds helper_vfp_adds_mips64 #define helper_vfp_cmpd helper_vfp_cmpd_mips64 +#define helper_vfp_cmph_a64 helper_vfp_cmph_a64_mips64 #define helper_vfp_cmped helper_vfp_cmped_mips64 +#define helper_vfp_cmpeh_a64 helper_vfp_cmpeh_a64_mips64 #define helper_vfp_cmpes helper_vfp_cmpes_mips64 #define helper_vfp_cmps helper_vfp_cmps_mips64 #define helper_vfp_divd helper_vfp_divd_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 4bcdbcb7..dbaede56 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -1658,7 +1658,9 @@ #define helper_vfp_addd helper_vfp_addd_mips64el #define helper_vfp_adds helper_vfp_adds_mips64el #define helper_vfp_cmpd helper_vfp_cmpd_mips64el +#define helper_vfp_cmph_a64 helper_vfp_cmph_a64_mips64el #define helper_vfp_cmped helper_vfp_cmped_mips64el +#define helper_vfp_cmpeh_a64 helper_vfp_cmpeh_a64_mips64el #define helper_vfp_cmpes helper_vfp_cmpes_mips64el #define helper_vfp_cmps helper_vfp_cmps_mips64el #define helper_vfp_divd helper_vfp_divd_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index c2e5068b..7a09d902 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -1658,7 +1658,9 @@ #define helper_vfp_addd helper_vfp_addd_mipsel #define helper_vfp_adds helper_vfp_adds_mipsel #define helper_vfp_cmpd helper_vfp_cmpd_mipsel +#define helper_vfp_cmph_a64 helper_vfp_cmph_a64_mipsel #define helper_vfp_cmped helper_vfp_cmped_mipsel +#define helper_vfp_cmpeh_a64 helper_vfp_cmpeh_a64_mipsel #define helper_vfp_cmpes helper_vfp_cmpes_mipsel #define helper_vfp_cmps helper_vfp_cmps_mipsel #define helper_vfp_divd helper_vfp_divd_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 282d6920..35cc9b17 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -1658,7 +1658,9 @@ #define helper_vfp_addd helper_vfp_addd_powerpc #define helper_vfp_adds helper_vfp_adds_powerpc #define helper_vfp_cmpd helper_vfp_cmpd_powerpc +#define helper_vfp_cmph_a64 helper_vfp_cmph_a64_powerpc #define helper_vfp_cmped helper_vfp_cmped_powerpc +#define helper_vfp_cmpeh_a64 helper_vfp_cmpeh_a64_powerpc #define helper_vfp_cmpes helper_vfp_cmpes_powerpc #define helper_vfp_cmps helper_vfp_cmps_powerpc #define helper_vfp_divd helper_vfp_divd_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index e8b83a43..82770cd1 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -1658,7 +1658,9 @@ #define helper_vfp_addd helper_vfp_addd_sparc #define helper_vfp_adds helper_vfp_adds_sparc #define helper_vfp_cmpd helper_vfp_cmpd_sparc +#define helper_vfp_cmph_a64 helper_vfp_cmph_a64_sparc #define helper_vfp_cmped helper_vfp_cmped_sparc +#define helper_vfp_cmpeh_a64 helper_vfp_cmpeh_a64_sparc #define helper_vfp_cmpes helper_vfp_cmpes_sparc #define helper_vfp_cmps helper_vfp_cmps_sparc #define helper_vfp_divd helper_vfp_divd_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index fcead175..56dfbc47 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -1658,7 +1658,9 @@ #define helper_vfp_addd helper_vfp_addd_sparc64 #define helper_vfp_adds helper_vfp_adds_sparc64 #define helper_vfp_cmpd helper_vfp_cmpd_sparc64 +#define helper_vfp_cmph_a64 helper_vfp_cmph_a64_sparc64 #define helper_vfp_cmped helper_vfp_cmped_sparc64 +#define helper_vfp_cmpeh_a64 helper_vfp_cmpeh_a64_sparc64 #define helper_vfp_cmpes helper_vfp_cmpes_sparc64 #define helper_vfp_cmps helper_vfp_cmps_sparc64 #define helper_vfp_divd helper_vfp_divd_sparc64 diff --git a/qemu/target/arm/helper-a64.c b/qemu/target/arm/helper-a64.c index f9d24a9b..1f3ab7e6 100644 --- a/qemu/target/arm/helper-a64.c +++ b/qemu/target/arm/helper-a64.c @@ -83,6 +83,16 @@ static inline uint32_t float_rel_to_flags(int res) return flags; } +uint64_t HELPER(vfp_cmph_a64)(float16 x, float16 y, void *fp_status) +{ + return float_rel_to_flags(float16_compare_quiet(x, y, fp_status)); +} + +uint64_t HELPER(vfp_cmpeh_a64)(float16 x, float16 y, void *fp_status) +{ + return float_rel_to_flags(float16_compare(x, y, fp_status)); +} + uint64_t HELPER(vfp_cmps_a64)(float32 x, float32 y, void *fp_status) { return float_rel_to_flags(float32_compare_quiet(x, y, fp_status)); diff --git a/qemu/target/arm/helper-a64.h b/qemu/target/arm/helper-a64.h index d691e15f..eab44cfa 100644 --- a/qemu/target/arm/helper-a64.h +++ b/qemu/target/arm/helper-a64.h @@ -19,6 +19,8 @@ DEF_HELPER_FLAGS_2(udiv64, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(sdiv64, TCG_CALL_NO_RWG_SE, s64, s64, s64) DEF_HELPER_FLAGS_1(rbit64, TCG_CALL_NO_RWG_SE, i64, i64) +DEF_HELPER_3(vfp_cmph_a64, i64, f16, f16, ptr) +DEF_HELPER_3(vfp_cmpeh_a64, i64, f16, f16, ptr) DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr) DEF_HELPER_3(vfp_cmpes_a64, i64, f32, f32, ptr) DEF_HELPER_3(vfp_cmpd_a64, i64, f64, f64, ptr) diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index f9b2bbb3..0b3c847b 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -4801,15 +4801,15 @@ static void disas_data_proc_reg(DisasContext *s, uint32_t insn) } } -static void handle_fp_compare(DisasContext *s, bool is_double, +static void handle_fp_compare(DisasContext *s, int size, unsigned int rn, unsigned int rm, bool cmp_with_zero, bool signal_all_nans) { 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, false); + TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, size == MO_16); - if (is_double) { + if (size == MO_64) { TCGv_i64 tcg_vn, tcg_vm; tcg_vn = read_fp_dreg(s, rn); @@ -4826,19 +4826,35 @@ static void handle_fp_compare(DisasContext *s, bool is_double, tcg_temp_free_i64(tcg_ctx, tcg_vn); tcg_temp_free_i64(tcg_ctx, tcg_vm); } else { - TCGv_i32 tcg_vn, tcg_vm; + TCGv_i32 tcg_vn = tcg_temp_new_i32(tcg_ctx); + TCGv_i32 tcg_vm = tcg_temp_new_i32(tcg_ctx); - tcg_vn = read_fp_sreg(s, rn); + read_vec_element_i32(s, tcg_vn, rn, 0, size); if (cmp_with_zero) { - tcg_vm = tcg_const_i32(tcg_ctx, 0); + tcg_gen_movi_i32(tcg_ctx, tcg_vm, 0); } else { - tcg_vm = read_fp_sreg(s, rm); + read_vec_element_i32(s, tcg_vm, rm, 0, size); } - if (signal_all_nans) { - gen_helper_vfp_cmpes_a64(tcg_ctx, tcg_flags, tcg_vn, tcg_vm, fpst); - } else { - gen_helper_vfp_cmps_a64(tcg_ctx, tcg_flags, tcg_vn, tcg_vm, fpst); + + switch (size) { + case MO_32: + if (signal_all_nans) { + gen_helper_vfp_cmpes_a64(tcg_ctx, tcg_flags, tcg_vn, tcg_vm, fpst); + } else { + gen_helper_vfp_cmps_a64(tcg_ctx, tcg_flags, tcg_vn, tcg_vm, fpst); + } + break; + case MO_16: + if (signal_all_nans) { + gen_helper_vfp_cmpeh_a64(tcg_ctx, tcg_flags, tcg_vn, tcg_vm, fpst); + } else { + gen_helper_vfp_cmph_a64(tcg_ctx, tcg_flags, tcg_vn, tcg_vm, fpst); + } + break; + default: + g_assert_not_reached(); } + tcg_temp_free_i32(tcg_ctx, tcg_vn); tcg_temp_free_i32(tcg_ctx, tcg_vm); } @@ -4859,16 +4875,35 @@ static void handle_fp_compare(DisasContext *s, bool is_double, static void disas_fp_compare(DisasContext *s, uint32_t insn) { unsigned int mos, type, rm, op, rn, opc, op2r; + int size; mos = extract32(insn, 29, 3); - type = extract32(insn, 22, 2); /* 0 = single, 1 = double */ + type = extract32(insn, 22, 2); rm = extract32(insn, 16, 5); op = extract32(insn, 14, 2); rn = extract32(insn, 5, 5); opc = extract32(insn, 3, 2); op2r = extract32(insn, 0, 3); - if (mos || op || op2r || type > 1) { + if (mos || op || op2r) { + unallocated_encoding(s); + return; + } + + switch (type) { + case 0: + size = MO_32; + break; + case 1: + size = MO_64; + break; + case 3: + size = MO_16; + if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { + break; + } + /* fallthru */ + default: unallocated_encoding(s); return; } @@ -4877,7 +4912,7 @@ static void disas_fp_compare(DisasContext *s, uint32_t insn) return; } - handle_fp_compare(s, type, rn, rm, opc & 1, opc & 2); + handle_fp_compare(s, size, rn, rm, opc & 1, opc & 2); } /* Floating point conditional compare @@ -4892,16 +4927,35 @@ static void disas_fp_ccomp(DisasContext *s, uint32_t insn) unsigned int mos, type, rm, cond, rn, op, nzcv; TCGv_i64 tcg_flags; TCGLabel *label_continue = NULL; + int size; mos = extract32(insn, 29, 3); - type = extract32(insn, 22, 2); /* 0 = single, 1 = double */ + type = extract32(insn, 22, 2); rm = extract32(insn, 16, 5); cond = extract32(insn, 12, 4); rn = extract32(insn, 5, 5); op = extract32(insn, 4, 1); nzcv = extract32(insn, 0, 4); - if (mos || type > 1) { + if (mos) { + unallocated_encoding(s); + return; + } + + switch (type) { + case 0: + size = MO_32; + break; + case 1: + size = MO_64; + break; + case 3: + size = MO_16; + if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { + break; + } + /* fallthru */ + default: unallocated_encoding(s); return; } @@ -4922,7 +4976,7 @@ static void disas_fp_ccomp(DisasContext *s, uint32_t insn) gen_set_label(tcg_ctx, label_match); } - handle_fp_compare(s, type, rn, rm, false, op); + handle_fp_compare(s, size, rn, rm, false, op); if (cond < 0x0e) { gen_set_label(tcg_ctx, label_continue); diff --git a/qemu/x86_64.h b/qemu/x86_64.h index fe388025..1b4c60fd 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -1658,7 +1658,9 @@ #define helper_vfp_addd helper_vfp_addd_x86_64 #define helper_vfp_adds helper_vfp_adds_x86_64 #define helper_vfp_cmpd helper_vfp_cmpd_x86_64 +#define helper_vfp_cmph_a64 helper_vfp_cmph_a64_x86_64 #define helper_vfp_cmped helper_vfp_cmped_x86_64 +#define helper_vfp_cmpeh_a64 helper_vfp_cmpeh_a64_x86_64 #define helper_vfp_cmpes helper_vfp_cmpes_x86_64 #define helper_vfp_cmps helper_vfp_cmps_x86_64 #define helper_vfp_divd helper_vfp_divd_x86_64