qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: qemu-arm@nongnu.org
Cc: qemu-devel@nongnu.org, "Alex Bennée" <alex.bennee@linaro.org>,
	"Peter Maydell" <peter.maydell@linaro.org>
Subject: [Qemu-devel] [PATCH v2 05/32] target/arm/cpu.h: add additional float_status flags
Date: Thu,  8 Feb 2018 17:31:30 +0000	[thread overview]
Message-ID: <20180208173157.24705-6-alex.bennee@linaro.org> (raw)
In-Reply-To: <20180208173157.24705-1-alex.bennee@linaro.org>

Half-precision flush to zero behaviour is controlled by a separate
FZ16 bit in the FPCR. To handle this we pass a pointer to
fp_status_fp16 when working on half-precision operations. The value of
the presented FPCR is calculated from an amalgam of the two when read.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 target/arm/cpu.h           | 22 +++++++++++++------
 target/arm/helper.c        | 12 +++++++++--
 target/arm/translate-a64.c | 53 +++++++++++++++++++++++++---------------------
 3 files changed, 55 insertions(+), 32 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index f976969011..97c9352a0f 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -501,19 +501,29 @@ typedef struct CPUARMState {
         /* scratch space when Tn are not sufficient.  */
         uint32_t scratch[8];
 
-        /* fp_status is the "normal" fp status. standard_fp_status retains
-         * values corresponding to the ARM "Standard FPSCR Value", ie
-         * default-NaN, flush-to-zero, round-to-nearest and is used by
-         * any operations (generally Neon) which the architecture defines
-         * as controlled by the standard FPSCR value rather than the FPSCR.
+        /* There are a number of distinct float control structures:
+         *
+         *  fp_status: is the "normal" fp status.
+         *  fp_status_fp16: used for half-precision calculations
+         *  standard_fp_status : the ARM "Standard FPSCR Value"
+         *
+         * Half-precision operations are governed by a separate
+         * flush-to-zero control bit in FPSCR:FZ16. We pass a separate
+         * status structure to control this.
+         *
+         * The "Standard FPSCR", ie default-NaN, flush-to-zero,
+         * round-to-nearest and is used by any operations (generally
+         * Neon) which the architecture defines as controlled by the
+         * standard FPSCR value rather than the FPSCR.
          *
          * To avoid having to transfer exception bits around, we simply
          * say that the FPSCR cumulative exception flags are the logical
-         * OR of the flags in the two fp statuses. This relies on the
+         * OR of the flags in the three fp statuses. This relies on the
          * only thing which needs to read the exception flags being
          * an explicit FPSCR read.
          */
         float_status fp_status;
+        float_status fp_status_f16;
         float_status standard_fp_status;
     } vfp;
     uint64_t exclusive_addr;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 4ef99882c4..1cc3d43a9f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -10692,6 +10692,7 @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
             | (env->vfp.vec_stride << 20);
     i = get_float_exception_flags(&env->vfp.fp_status);
     i |= get_float_exception_flags(&env->vfp.standard_fp_status);
+    i |= get_float_exception_flags(&env->vfp.fp_status_f16);
     fpscr |= vfp_exceptbits_from_host(i);
     return fpscr;
 }
@@ -10750,15 +10751,22 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
         }
         set_float_rounding_mode(i, &env->vfp.fp_status);
     }
-    if (changed & (1 << 24)) {
+    if (changed & (1 << 19)) { /* FPCR:FZ16 */
+        set_flush_to_zero((val & (1 << 19)) != 0, &env->vfp.fp_status_f16);
+        set_flush_inputs_to_zero((val & (1 << 19)) != 0,
+                                 &env->vfp.fp_status_f16);
+    }
+    if (changed & (1 << 24)) { /* FPCR:FZ */
         set_flush_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
         set_flush_inputs_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
     }
-    if (changed & (1 << 25))
+    if (changed & (1 << 25)) { /* FPCR:DN */
         set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status);
+    }
 
     i = vfp_exceptbits_to_host(val);
     set_float_exception_flags(i, &env->vfp.fp_status);
+    set_float_exception_flags(i, &env->vfp.fp_status_f16);
     set_float_exception_flags(0, &env->vfp.standard_fp_status);
 }
 
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index eed64c73e5..1afa669e6e 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -604,16 +604,21 @@ static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
     tcg_temp_free_i64(tmp);
 }
 
-static TCGv_ptr get_fpstatus_ptr(void)
+static TCGv_ptr get_fpstatus_ptr(bool is_f16)
 {
     TCGv_ptr statusptr = tcg_temp_new_ptr();
     int offset;
 
-    /* In A64 all instructions (both FP and Neon) use the FPCR;
-     * there is no equivalent of the A32 Neon "standard FPSCR value"
-     * and all operations use vfp.fp_status.
+    /* In A64 all instructions (both FP and Neon) use the FPCR; there
+     * is no equivalent of the A32 Neon "standard FPSCR value".
+     * However half-precision operations operate under a different
+     * FZ16 flag and use vfp.fp_status_f16 instead of vfp.fp_status.
      */
-    offset = offsetof(CPUARMState, vfp.fp_status);
+    if (is_f16) {
+        offset = offsetof(CPUARMState, vfp.fp_status_f16);
+    } else {
+        offset = offsetof(CPUARMState, vfp.fp_status);
+    }
     tcg_gen_addi_ptr(statusptr, cpu_env, offset);
     return statusptr;
 }
@@ -4335,7 +4340,7 @@ static void handle_fp_compare(DisasContext *s, bool is_double,
                               bool cmp_with_zero, bool signal_all_nans)
 {
     TCGv_i64 tcg_flags = tcg_temp_new_i64();
-    TCGv_ptr fpst = get_fpstatus_ptr();
+    TCGv_ptr fpst = get_fpstatus_ptr(false);
 
     if (is_double) {
         TCGv_i64 tcg_vn, tcg_vm;
@@ -4510,7 +4515,7 @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
     TCGv_i32 tcg_op;
     TCGv_i32 tcg_res;
 
-    fpst = get_fpstatus_ptr();
+    fpst = get_fpstatus_ptr(false);
     tcg_op = read_fp_sreg(s, rn);
     tcg_res = tcg_temp_new_i32();
 
@@ -4566,7 +4571,7 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
     TCGv_i64 tcg_op;
     TCGv_i64 tcg_res;
 
-    fpst = get_fpstatus_ptr();
+    fpst = get_fpstatus_ptr(false);
     tcg_op = read_fp_dreg(s, rn);
     tcg_res = tcg_temp_new_i64();
 
@@ -4749,7 +4754,7 @@ static void handle_fp_2src_single(DisasContext *s, int opcode,
     TCGv_ptr fpst;
 
     tcg_res = tcg_temp_new_i32();
-    fpst = get_fpstatus_ptr();
+    fpst = get_fpstatus_ptr(false);
     tcg_op1 = read_fp_sreg(s, rn);
     tcg_op2 = read_fp_sreg(s, rm);
 
@@ -4802,7 +4807,7 @@ static void handle_fp_2src_double(DisasContext *s, int opcode,
     TCGv_ptr fpst;
 
     tcg_res = tcg_temp_new_i64();
-    fpst = get_fpstatus_ptr();
+    fpst = get_fpstatus_ptr(false);
     tcg_op1 = read_fp_dreg(s, rn);
     tcg_op2 = read_fp_dreg(s, rm);
 
@@ -4888,7 +4893,7 @@ static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1,
 {
     TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
     TCGv_i32 tcg_res = tcg_temp_new_i32();
-    TCGv_ptr fpst = get_fpstatus_ptr();
+    TCGv_ptr fpst = get_fpstatus_ptr(false);
 
     tcg_op1 = read_fp_sreg(s, rn);
     tcg_op2 = read_fp_sreg(s, rm);
@@ -4926,7 +4931,7 @@ static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1,
 {
     TCGv_i64 tcg_op1, tcg_op2, tcg_op3;
     TCGv_i64 tcg_res = tcg_temp_new_i64();
-    TCGv_ptr fpst = get_fpstatus_ptr();
+    TCGv_ptr fpst = get_fpstatus_ptr(false);
 
     tcg_op1 = read_fp_dreg(s, rn);
     tcg_op2 = read_fp_dreg(s, rm);
@@ -5067,7 +5072,7 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
     TCGv_ptr tcg_fpstatus;
     TCGv_i32 tcg_shift;
 
-    tcg_fpstatus = get_fpstatus_ptr();
+    tcg_fpstatus = get_fpstatus_ptr(false);
 
     tcg_shift = tcg_const_i32(64 - scale);
 
@@ -5779,7 +5784,7 @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
         TCGv_i32 tcg_elt1 = tcg_temp_new_i32();
         TCGv_i32 tcg_elt2 = tcg_temp_new_i32();
         TCGv_i32 tcg_elt3 = tcg_temp_new_i32();
-        TCGv_ptr fpst = get_fpstatus_ptr();
+        TCGv_ptr fpst = get_fpstatus_ptr(false);
 
         assert(esize == 32);
         assert(elements == 4);
@@ -6314,7 +6319,7 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
         }
 
         size = extract32(size, 0, 1) ? 3 : 2;
-        fpst = get_fpstatus_ptr();
+        fpst = get_fpstatus_ptr(false);
         break;
     default:
         unallocated_encoding(s);
@@ -6824,7 +6829,7 @@ static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn,
                                    int fracbits, int size)
 {
     bool is_double = size == 3 ? true : false;
-    TCGv_ptr tcg_fpst = get_fpstatus_ptr();
+    TCGv_ptr tcg_fpst = get_fpstatus_ptr(false);
     TCGv_i32 tcg_shift = tcg_const_i32(fracbits);
     TCGv_i64 tcg_int = tcg_temp_new_i64();
     TCGMemOp mop = size | (is_signed ? MO_SIGN : 0);
@@ -6942,7 +6947,7 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
 
     tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
     gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
-    tcg_fpstatus = get_fpstatus_ptr();
+    tcg_fpstatus = get_fpstatus_ptr(false);
     tcg_shift = tcg_const_i32(fracbits);
 
     if (is_double) {
@@ -7271,7 +7276,7 @@ static void handle_3same_float(DisasContext *s, int size, int elements,
                                int fpopcode, int rd, int rn, int rm)
 {
     int pass;
-    TCGv_ptr fpst = get_fpstatus_ptr();
+    TCGv_ptr fpst = get_fpstatus_ptr(false);
 
     for (pass = 0; pass < elements; pass++) {
         if (size) {
@@ -7738,7 +7743,7 @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
         return;
     }
 
-    fpst = get_fpstatus_ptr();
+    fpst = get_fpstatus_ptr(false);
 
     if (is_double) {
         TCGv_i64 tcg_op = tcg_temp_new_i64();
@@ -7847,7 +7852,7 @@ static void handle_2misc_reciprocal(DisasContext *s, int opcode,
                                     int size, int rn, int rd)
 {
     bool is_double = (size == 3);
-    TCGv_ptr fpst = get_fpstatus_ptr();
+    TCGv_ptr fpst = get_fpstatus_ptr(false);
 
     if (is_double) {
         TCGv_i64 tcg_op = tcg_temp_new_i64();
@@ -8258,7 +8263,7 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
     if (is_fcvt) {
         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
         gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
-        tcg_fpstatus = get_fpstatus_ptr();
+        tcg_fpstatus = get_fpstatus_ptr(false);
     } else {
         tcg_rmode = NULL;
         tcg_fpstatus = NULL;
@@ -9187,7 +9192,7 @@ static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
 
     /* Floating point operations need fpst */
     if (opcode >= 0x58) {
-        fpst = get_fpstatus_ptr();
+        fpst = get_fpstatus_ptr(false);
     } else {
         fpst = NULL;
     }
@@ -10245,7 +10250,7 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
     }
 
     if (need_fpstatus) {
-        tcg_fpstatus = get_fpstatus_ptr();
+        tcg_fpstatus = get_fpstatus_ptr(false);
     } else {
         tcg_fpstatus = NULL;
     }
@@ -10612,7 +10617,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
     }
 
     if (is_fp) {
-        fpst = get_fpstatus_ptr();
+        fpst = get_fpstatus_ptr(false);
     } else {
         fpst = NULL;
     }
-- 
2.15.1

  parent reply	other threads:[~2018-02-08 17:32 UTC|newest]

Thread overview: 79+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-08 17:31 [Qemu-devel] [PATCH v2 00/32] Add ARMv8.2 half-precision functions Alex Bennée
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 01/32] include/exec/helper-head.h: support f16 in helper calls Alex Bennée
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 02/32] target/arm/cpu64: introduce ARM_V8_FP16 feature bit Alex Bennée
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 03/32] target/arm/cpu64: allow fp16 to be disabled Alex Bennée
2018-02-08 20:36   ` Richard Henderson
2018-02-13 14:26   ` Peter Maydell
2018-02-21 16:35     ` Alex Bennée
2018-02-21 18:16       ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 04/32] target/arm/cpu.h: update comment for half-precision values Alex Bennée
2018-02-08 17:31 ` Alex Bennée [this message]
2018-02-08 20:42   ` [Qemu-devel] [PATCH v2 05/32] target/arm/cpu.h: add additional float_status flags Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 06/32] target/arm/helper: pass explicit fpst to set_rmode Alex Bennée
2018-02-08 20:43   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 07/32] arm/translate-a64: implement half-precision F(MIN|MAX)(V|NMV) Alex Bennée
2018-02-08 20:46   ` Richard Henderson
2018-02-08 20:49   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 08/32] arm/translate-a64: handle_3same_64 comment fix Alex Bennée
2018-02-08 20:46   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 09/32] arm/translate-a64: initial decode for simd_three_reg_same_fp16 Alex Bennée
2018-02-08 20:48   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 10/32] arm/translate-a64: add FP16 FADD/FABD/FSUB/FMUL/FDIV to simd_three_reg_same_fp16 Alex Bennée
2018-02-08 20:49   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 11/32] arm/translate-a64: add FP16 F[A]C[EQ/GE/GT] " Alex Bennée
2018-02-08 20:54   ` Richard Henderson
2018-02-23 11:59     ` Alex Bennée
2018-02-23 22:10       ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 12/32] arm/translate-a64: add FP16 FMULA/X/S " Alex Bennée
2018-02-08 20:56   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 13/32] arm/translate-a64: add FP16 FR[ECP/SQRT]S " Alex Bennée
2018-02-08 20:59   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 14/32] arm/translate-a64: add FP16 pairwise ops simd_three_reg_same_fp16 Alex Bennée
2018-02-08 21:30   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 15/32] arm/translate-a64: add FP16 FMULX/MLS/FMLA to simd_indexed Alex Bennée
2018-02-08 21:49   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 16/32] arm/translate-a64: add FP16 x2 ops for simd_indexed Alex Bennée
2018-02-08 22:10   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 17/32] arm/translate-a64: initial decode for simd_two_reg_misc_fp16 Alex Bennée
2018-02-08 22:15   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 18/32] arm/translate-a64: add FP16 FPRINTx to simd_two_reg_misc_fp16 Alex Bennée
2018-02-08 22:32   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 19/32] arm/translate-a64: add FCVTxx " Alex Bennée
2018-02-08 22:35   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 20/32] arm/translate-a64: add FP16 FCMxx (zero) " Alex Bennée
2018-02-08 22:39   ` Richard Henderson
2018-02-22 17:23     ` Alex Bennée
2018-02-22 19:40       ` Richard Henderson
2018-02-23 10:23         ` Alex Bennée
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 21/32] arm/translate-a64: add FP16 SCVTF/UCVFT " Alex Bennée
2018-02-08 22:42   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 22/32] arm/translate-a64: add FP16 FNEG/FABS " Alex Bennée
2018-02-08 22:43   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 23/32] arm/helper.c: re-factor recpe and add recepe_f16 Alex Bennée
2018-02-09 17:54   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 24/32] arm/translate-a64: add FP16 FRECPE Alex Bennée
2018-02-09 17:57   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 25/32] arm/translate-a64: add FP16 FRCPX to simd_two_reg_misc_fp16 Alex Bennée
2018-02-09 18:00   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 26/32] arm/translate-a64: add FP16 FSQRT " Alex Bennée
2018-02-09 18:01   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 27/32] arm/helper.c: re-factor rsqrte and add rsqrte_f16 Alex Bennée
2018-02-09 18:15   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 28/32] arm/translate-a64: add FP16 FRSQRTE to simd_two_reg_misc_fp16 Alex Bennée
2018-02-09 18:15   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 29/32] arm/translate-a64: add FP16 FMOV to simd_mod_imm Alex Bennée
2018-02-09 18:23   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 30/32] arm/translate-a64: add all FP16 ops in simd_scalar_pairwise Alex Bennée
2018-02-09 18:27   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 31/32] arm/translate-a64: implement simd_scalar_three_reg_same_fp16 Alex Bennée
2018-02-09 18:34   ` Richard Henderson
2018-02-08 17:31 ` [Qemu-devel] [PATCH v2 32/32] arm/translate-a64: add all single op FP16 to handle_fp_1src_half Alex Bennée
2018-02-09 18:37   ` Richard Henderson
2018-02-23  9:45     ` Alex Bennée
2018-02-08 18:49 ` [Qemu-devel] [PATCH v2 00/32] Add ARMv8.2 half-precision functions no-reply
2018-02-08 18:56 ` no-reply
2018-02-08 19:04 ` no-reply
2018-02-08 19:11 ` no-reply
2018-02-08 19:17 ` no-reply
2018-02-08 21:33 ` no-reply
2018-02-13 14:27 ` [Qemu-devel] [Qemu-arm] " Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180208173157.24705-6-alex.bennee@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).