qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Sagar Karandikar <sagark@eecs.berkeley.edu>
To: qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org, rth@twiddle.net,
	kbastian@mail.uni-paderborn.de,
	Sagar Karandikar <sagark@eecs.berkeley.edu>
Subject: [Qemu-devel] [PATCH 09/18] target-riscv: Add FMADD, FMSUB, FNMADD, FNMSUB Instructions,
Date: Mon, 26 Sep 2016 03:56:39 -0700	[thread overview]
Message-ID: <0d19d4ba3bdde064e0cb77b9c533373f964c24ee.1474886798.git.sagark@eecs.berkeley.edu> (raw)
In-Reply-To: <cover.1474886798.git.sagark@eecs.berkeley.edu>
In-Reply-To: <cover.1474886798.git.sagark@eecs.berkeley.edu>

Along with FP helper infrastructure, changes to softfloat-specialize

Signed-off-by: Sagar Karandikar <sagark@eecs.berkeley.edu>
---
 fpu/softfloat-specialize.h |   7 ++-
 target-riscv/Makefile.objs |   2 +-
 target-riscv/fpu_helper.c  | 151 +++++++++++++++++++++++++++++++++++++++++++++
 target-riscv/helper.h      |  10 +++
 target-riscv/translate.c   | 105 +++++++++++++++++++++++++++++++
 5 files changed, 271 insertions(+), 4 deletions(-)
 create mode 100644 target-riscv/fpu_helper.c

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index f5aed72..fa5986d 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -114,7 +114,8 @@ float32 float32_default_nan(float_status *status)
 #if defined(TARGET_SPARC)
     return const_float32(0x7FFFFFFF);
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
-      defined(TARGET_XTENSA) || defined(TARGET_S390X) || defined(TARGET_TRICORE)
+      defined(TARGET_XTENSA) || defined(TARGET_S390X) || \
+      defined(TARGET_TRICORE) || defined(TARGET_RISCV)
     return const_float32(0x7FC00000);
 #else
     if (status->snan_bit_is_one) {
@@ -137,7 +138,7 @@ float64 float64_default_nan(float_status *status)
 #if defined(TARGET_SPARC)
     return const_float64(LIT64(0x7FFFFFFFFFFFFFFF));
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
-      defined(TARGET_S390X)
+      defined(TARGET_S390X) || defined(TARGET_RISCV)
     return const_float64(LIT64(0x7FF8000000000000));
 #else
     if (status->snan_bit_is_one) {
@@ -181,7 +182,7 @@ float128 float128_default_nan(float_status *status)
         r.high = LIT64(0x7FFF7FFFFFFFFFFF);
     } else {
         r.low = LIT64(0x0000000000000000);
-#if defined(TARGET_S390X)
+#if defined(TARGET_S390X) || defined(TARGET_RISCV)
         r.high = LIT64(0x7FFF800000000000);
 #else
         r.high = LIT64(0xFFFF800000000000);
diff --git a/target-riscv/Makefile.objs b/target-riscv/Makefile.objs
index cb448a8..0149732 100644
--- a/target-riscv/Makefile.objs
+++ b/target-riscv/Makefile.objs
@@ -1 +1 @@
-obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += translate.o op_helper.o helper.o cpu.o fpu_helper.o
diff --git a/target-riscv/fpu_helper.c b/target-riscv/fpu_helper.c
new file mode 100644
index 0000000..9023d10
--- /dev/null
+++ b/target-riscv/fpu_helper.c
@@ -0,0 +1,151 @@
+/*
+ * RISC-V FPU Emulation Helpers for QEMU.
+ *
+ * Author: Sagar Karandikar, sagark@eecs.berkeley.edu
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include <stdlib.h>
+#include "cpu.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+
+/* convert RISC-V rounding mode to IEEE library numbers */
+unsigned int ieee_rm[] = {
+    float_round_nearest_even,
+    float_round_to_zero,
+    float_round_down,
+    float_round_up,
+    float_round_ties_away
+};
+
+/* obtain rm value to use in computation
+ * as the last step, convert rm codes to what the softfloat library expects
+ * Adapted from Spike's decode.h:RM
+ */
+#define RM ({                                             \
+if (rm == 7) {                                            \
+    rm = env->csr[CSR_FRM];                               \
+}                                                         \
+if (rm > 4) {                                             \
+    helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST); \
+}                                                         \
+ieee_rm[rm]; })
+
+/* convert softfloat library flag numbers to RISC-V */
+unsigned int softfloat_flags_to_riscv(unsigned int flag)
+{
+    switch (flag) {
+    case float_flag_inexact:
+        return 1;
+    case float_flag_underflow:
+        return 2;
+    case float_flag_overflow:
+        return 4;
+    case float_flag_divbyzero:
+        return 8;
+    case float_flag_invalid:
+        return 16;
+    default:
+        return 0;
+    }
+}
+
+/* adapted from Spike's decode.h:set_fp_exceptions */
+#define set_fp_exceptions() do { \
+    env->csr[CSR_FFLAGS] |= softfloat_flags_to_riscv(get_float_exception_flags(\
+                            &env->fp_status)); \
+    set_float_exception_flags(0, &env->fp_status); \
+} while (0)
+
+uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+                        uint64_t frs3, uint64_t rm)
+{
+    set_float_rounding_mode(RM, &env->fp_status);
+    frs1 = float32_muladd(frs1, frs2, frs3, 0, &env->fp_status);
+    set_fp_exceptions();
+    return frs1;
+}
+
+uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+                        uint64_t frs3, uint64_t rm)
+{
+    set_float_rounding_mode(RM, &env->fp_status);
+    frs1 = float64_muladd(frs1, frs2, frs3, 0, &env->fp_status);
+    set_fp_exceptions();
+    return frs1;
+}
+
+uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+                        uint64_t frs3, uint64_t rm)
+{
+    set_float_rounding_mode(RM, &env->fp_status);
+    frs1 = float32_muladd(frs1, frs2, frs3 ^ (uint32_t)INT32_MIN, 0,
+                          &env->fp_status);
+    set_fp_exceptions();
+    return frs1;
+}
+
+uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+                        uint64_t frs3, uint64_t rm)
+{
+    set_float_rounding_mode(RM, &env->fp_status);
+    frs1 = float64_muladd(frs1, frs2, frs3 ^ (uint64_t)INT64_MIN, 0,
+                          &env->fp_status);
+    set_fp_exceptions();
+    return frs1;
+}
+
+uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+                         uint64_t frs3, uint64_t rm)
+{
+    set_float_rounding_mode(RM, &env->fp_status);
+    frs1 = float32_muladd(frs1 ^ (uint32_t)INT32_MIN, frs2, frs3, 0,
+                          &env->fp_status);
+    set_fp_exceptions();
+    return frs1;
+}
+
+uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+                         uint64_t frs3, uint64_t rm)
+{
+    set_float_rounding_mode(RM, &env->fp_status);
+    frs1 = float64_muladd(frs1 ^ (uint64_t)INT64_MIN, frs2, frs3, 0,
+                          &env->fp_status);
+    set_fp_exceptions();
+    return frs1;
+}
+
+uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+                         uint64_t frs3, uint64_t rm)
+{
+    set_float_rounding_mode(RM, &env->fp_status);
+    frs1 = float32_muladd(frs1 ^ (uint32_t)INT32_MIN, frs2,
+                          frs3 ^ (uint32_t)INT32_MIN, 0, &env->fp_status);
+    set_fp_exceptions();
+    return frs1;
+}
+
+uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+                         uint64_t frs3, uint64_t rm)
+{
+    set_float_rounding_mode(RM, &env->fp_status);
+    frs1 = float64_muladd(frs1 ^ (uint64_t)INT64_MIN, frs2,
+                          frs3 ^ (uint64_t)INT64_MIN, 0, &env->fp_status);
+    set_fp_exceptions();
+    return frs1;
+}
diff --git a/target-riscv/helper.h b/target-riscv/helper.h
index c489222..586abae5 100644
--- a/target-riscv/helper.h
+++ b/target-riscv/helper.h
@@ -6,3 +6,13 @@ DEF_HELPER_3(raise_exception_mbadaddr, noreturn, env, i32, tl)
 #if defined(TARGET_RISCV64)
 DEF_HELPER_FLAGS_3(mulhsu, TCG_CALL_NO_RWG_SE, tl, env, tl, tl)
 #endif
+
+/* Floating Point - fused */
+DEF_HELPER_FLAGS_5(fmadd_s, TCG_CALL_NO_RWG, i64, env, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_5(fmadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_5(fmsub_s, TCG_CALL_NO_RWG, i64, env, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_5(fmsub_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_5(fnmsub_s, TCG_CALL_NO_RWG, i64, env, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_5(fnmsub_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_5(fnmadd_s, TCG_CALL_NO_RWG, i64, env, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_5(fnmadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64, i64)
diff --git a/target-riscv/translate.c b/target-riscv/translate.c
index af82eab..07f24e8 100644
--- a/target-riscv/translate.c
+++ b/target-riscv/translate.c
@@ -792,6 +792,95 @@ static inline void gen_atomic(DisasContext *ctx, uint32_t opc,
     tcg_temp_free(dat);
 }
 
+static inline void gen_fp_fmadd(DisasContext *ctx, uint32_t opc, int rd,
+        int rs1, int rs2, int rs3, int rm)
+{
+    TCGv_i64 rm_reg = tcg_temp_new_i64();
+    tcg_gen_movi_i64(rm_reg, rm);
+
+    switch (opc) {
+    case OPC_RISC_FMADD_S:
+        gen_helper_fmadd_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2],
+                           cpu_fpr[rs3], rm_reg);
+        break;
+    case OPC_RISC_FMADD_D:
+        gen_helper_fmadd_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2],
+                           cpu_fpr[rs3], rm_reg);
+        break;
+    default:
+        kill_unknown(ctx, RISCV_EXCP_ILLEGAL_INST);
+        break;
+    }
+    tcg_temp_free_i64(rm_reg);
+
+}
+
+static inline void gen_fp_fmsub(DisasContext *ctx, uint32_t opc, int rd,
+        int rs1, int rs2, int rs3, int rm)
+{
+    TCGv_i64 rm_reg = tcg_temp_new_i64();
+    tcg_gen_movi_i64(rm_reg, rm);
+
+    switch (opc) {
+    case OPC_RISC_FMSUB_S:
+        gen_helper_fmsub_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2],
+                           cpu_fpr[rs3], rm_reg);
+        break;
+    case OPC_RISC_FMSUB_D:
+        gen_helper_fmsub_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2],
+                           cpu_fpr[rs3], rm_reg);
+        break;
+    default:
+        kill_unknown(ctx, RISCV_EXCP_ILLEGAL_INST);
+        break;
+    }
+    tcg_temp_free_i64(rm_reg);
+}
+
+static inline void gen_fp_fnmsub(DisasContext *ctx, uint32_t opc, int rd,
+        int rs1, int rs2, int rs3, int rm)
+{
+    TCGv_i64 rm_reg = tcg_temp_new_i64();
+    tcg_gen_movi_i64(rm_reg, rm);
+
+    switch (opc) {
+    case OPC_RISC_FNMSUB_S:
+        gen_helper_fnmsub_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2],
+                            cpu_fpr[rs3], rm_reg);
+        break;
+    case OPC_RISC_FNMSUB_D:
+        gen_helper_fnmsub_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2],
+                            cpu_fpr[rs3], rm_reg);
+        break;
+    default:
+        kill_unknown(ctx, RISCV_EXCP_ILLEGAL_INST);
+        break;
+    }
+    tcg_temp_free_i64(rm_reg);
+}
+
+static inline void gen_fp_fnmadd(DisasContext *ctx, uint32_t opc, int rd,
+        int rs1, int rs2, int rs3, int rm)
+{
+    TCGv_i64 rm_reg = tcg_temp_new_i64();
+    tcg_gen_movi_i64(rm_reg, rm);
+
+    switch (opc) {
+    case OPC_RISC_FNMADD_S:
+        gen_helper_fnmadd_s(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2],
+                            cpu_fpr[rs3], rm_reg);
+        break;
+    case OPC_RISC_FNMADD_D:
+        gen_helper_fnmadd_d(cpu_fpr[rd], cpu_env, cpu_fpr[rs1], cpu_fpr[rs2],
+                            cpu_fpr[rs3], rm_reg);
+        break;
+    default:
+        kill_unknown(ctx, RISCV_EXCP_ILLEGAL_INST);
+        break;
+    }
+    tcg_temp_free_i64(rm_reg);
+}
+
 static void decode_opc(CPURISCVState *env, DisasContext *ctx)
 {
     int rs1;
@@ -900,6 +989,22 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx)
     case OPC_RISC_ATOMIC:
         gen_atomic(ctx, MASK_OP_ATOMIC(ctx->opcode), rd, rs1, rs2);
         break;
+    case OPC_RISC_FMADD:
+        gen_fp_fmadd(ctx, MASK_OP_FP_FMADD(ctx->opcode), rd, rs1, rs2,
+                     GET_RS3(ctx->opcode), GET_RM(ctx->opcode));
+        break;
+    case OPC_RISC_FMSUB:
+        gen_fp_fmsub(ctx, MASK_OP_FP_FMSUB(ctx->opcode), rd, rs1, rs2,
+                     GET_RS3(ctx->opcode), GET_RM(ctx->opcode));
+        break;
+    case OPC_RISC_FNMSUB:
+        gen_fp_fnmsub(ctx, MASK_OP_FP_FNMSUB(ctx->opcode), rd, rs1, rs2,
+                      GET_RS3(ctx->opcode), GET_RM(ctx->opcode));
+        break;
+    case OPC_RISC_FNMADD:
+        gen_fp_fnmadd(ctx, MASK_OP_FP_FNMADD(ctx->opcode), rd, rs1, rs2,
+                      GET_RS3(ctx->opcode), GET_RM(ctx->opcode));
+        break;
     default:
         kill_unknown(ctx, RISCV_EXCP_ILLEGAL_INST);
         break;
-- 
2.9.3

  parent reply	other threads:[~2016-09-26 11:31 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-26 10:56 [Qemu-devel] [PATCH 00/18] target-riscv: Add full-system emulation support for the RISC-V Instruction Set Architecture (RV64G, RV32G) Sagar Karandikar
2016-09-26 10:56 ` [Qemu-devel] [PATCH 01/18] target-riscv: Add RISC-V target stubs and Maintainer Sagar Karandikar
2016-09-26 19:06   ` Eric Blake
2016-09-26 10:56 ` [Qemu-devel] [PATCH 02/18] target-riscv: Add RISC-V Target stubs inside target-riscv/ Sagar Karandikar
2016-09-26 16:30   ` Richard Henderson
2016-09-26 21:50   ` Richard Henderson
2016-09-26 10:56 ` [Qemu-devel] [PATCH 03/18] target-riscv: Add initialization for translation Sagar Karandikar
2016-09-26 16:34   ` Richard Henderson
2016-09-26 10:56 ` [Qemu-devel] [PATCH 04/18] target-riscv: Add framework for instruction decode Sagar Karandikar
2016-09-26 16:49   ` Richard Henderson
2016-09-26 10:56 ` [Qemu-devel] [PATCH 05/18] target-riscv: Add Arithmetic instructions Sagar Karandikar
2016-09-26 17:31   ` Richard Henderson
2016-09-26 10:56 ` [Qemu-devel] [PATCH 06/18] target-riscv: Add JALR, Branch Instructions Sagar Karandikar
2016-09-26 18:28   ` Richard Henderson
2016-09-26 10:56 ` [Qemu-devel] [PATCH 07/18] target-riscv: Add Loads/Stores, FP Loads/Stores Sagar Karandikar
2016-09-26 20:44   ` Richard Henderson
2016-09-26 10:56 ` [Qemu-devel] [PATCH 08/18] target-riscv: Add Atomic Instructions Sagar Karandikar
2016-09-27 19:30   ` Richard Henderson
2016-09-26 10:56 ` Sagar Karandikar [this message]
2016-09-26 21:15   ` [Qemu-devel] [PATCH 09/18] target-riscv: Add FMADD, FMSUB, FNMADD, FNMSUB Instructions, Richard Henderson
2016-09-27 19:20   ` Richard Henderson
2016-09-26 10:56 ` [Qemu-devel] [PATCH 10/18] target-riscv: Add Single Precision Floating-Point Instructions Sagar Karandikar
2016-09-26 21:35   ` Richard Henderson
2016-09-26 10:56 ` [Qemu-devel] [PATCH 11/18] target-riscv: Add Double " Sagar Karandikar
2016-09-26 21:37   ` Richard Henderson
2016-09-26 10:56 ` [Qemu-devel] [PATCH 12/18] target-riscv: Add system instructions Sagar Karandikar
2016-09-26 12:21   ` Paolo Bonzini
2016-09-26 12:38     ` Bastian Koppelmann
2016-09-26 12:44       ` Paolo Bonzini
2016-09-27 18:12         ` Sagar Karandikar
2016-09-26 21:41   ` Richard Henderson
2016-09-26 10:56 ` [Qemu-devel] [PATCH 13/18] target-riscv: Add CSR read/write helpers Sagar Karandikar
2016-09-26 10:56 ` [Qemu-devel] [PATCH 14/18] target-riscv: softmmu/address translation support Sagar Karandikar
2016-09-26 22:04   ` Richard Henderson
2016-09-26 10:56 ` [Qemu-devel] [PATCH 15/18] target-riscv: Interrupt Handling Sagar Karandikar
2016-09-26 22:07   ` Richard Henderson
2016-09-26 10:56 ` [Qemu-devel] [PATCH 16/18] target-riscv: Timer Support Sagar Karandikar
2016-09-26 10:56 ` [Qemu-devel] [PATCH 17/18] target-riscv: Add support for Host-Target Interface (HTIF) Devices Sagar Karandikar
2016-09-26 10:56 ` [Qemu-devel] [PATCH 18/18] target-riscv: Add generic test board, activate target Sagar Karandikar
2016-09-26 12:20 ` [Qemu-devel] [PATCH 00/18] target-riscv: Add full-system emulation support for the RISC-V Instruction Set Architecture (RV64G, RV32G) Paolo Bonzini
2016-09-26 16:17   ` Richard Henderson
2016-09-26 16:20     ` Andreas Färber
2016-09-26 16:24       ` Paolo Bonzini
2016-09-26 16:35         ` Andreas Färber
2016-09-26 16:37           ` Paolo Bonzini

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=0d19d4ba3bdde064e0cb77b9c533373f964c24ee.1474886798.git.sagark@eecs.berkeley.edu \
    --to=sagark@eecs.berkeley.edu \
    --cc=kbastian@mail.uni-paderborn.de \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    /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).