qemu-riscv
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 6/8] target/riscv: Support of compiler's 128-bit integer types


From: Frédéric Pétrot
Subject: [PATCH 6/8] target/riscv: Support of compiler's 128-bit integer types
Date: Mon, 30 Aug 2021 19:16:36 +0200

128-bit mult and div helpers may now use the compiler support
for 128-bit integers if it exists.

Signed-off-by: Frédéric Pétrot <frederic.petrot@univ-grenoble-alpes.fr>
Co-authored-by: Fabien Portas <fabien.portas@grenoble-inp.org>
---
 target/riscv/cpu.h         | 13 +++++++++++
 target/riscv/m128_helper.c | 48 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6528b4540e..4321b03b94 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -60,6 +60,19 @@
 #define RV64 ((target_ulong)2 << (TARGET_LONG_BITS - 2))
 /* To be used on misah, the upper part of misa */
 #define RV128 ((target_ulong)3 << (TARGET_LONG_BITS - 2))
+/*
+ * Defined to force the use of tcg 128-bit arithmetic
+ * if the compiler does not have a 128-bit built-in type
+ */
+#define SOFT_128BIT
+/*
+ * If available and not explicitly disabled,
+ * use compiler's 128-bit integers.
+ */
+#if defined(__SIZEOF_INT128__) && !defined(SOFT_128BIT)
+#define HARD_128BIT
+#endif
+
 
 #define RV(x) ((target_ulong)1 << (x - 'A'))
 
diff --git a/target/riscv/m128_helper.c b/target/riscv/m128_helper.c
index 973632b005..bf50525ec0 100644
--- a/target/riscv/m128_helper.c
+++ b/target/riscv/m128_helper.c
@@ -24,6 +24,7 @@
 #include "exec/helper-proto.h"
 
 #ifdef TARGET_RISCV128
+#ifndef HARD_128BIT
 /* TODO : This can be optimized by a lot */
 static void divmod128(uint64_t ul, uint64_t uh,
             uint64_t vl, uint64_t vh,
@@ -175,6 +176,7 @@ static void divmod128(uint64_t ul, uint64_t uh,
         *rh = r[2] | ((uint64_t)r[3] << 32);
     }
 }
+#endif
 
 void HELPER(idivu128)(CPURISCVState *env, uint64_t rd,
                         uint64_t ul, uint64_t uh,
@@ -185,8 +187,19 @@ void HELPER(idivu128)(CPURISCVState *env, uint64_t rd,
         ql = 0xffffffffffffffff;
         qh = ql;
     } else {
+#ifdef HARD_128BIT
+        /* If available, use builtin 128-bit type */
+        __uint128_t u = (((__uint128_t) uh) << 64) | ul,
+                    v = (((__uint128_t) vh) << 64) | vl,
+                    r;
+
+        r = u / v;
+        ql = r & 0xffffffffffffffff;
+        qh = (r >> 64) & 0xffffffffffffffff;
+#else
         /* Soft quad division */
         divmod128(ul, uh, vl, vh, &ql, &qh, NULL, NULL);
+#endif
     }
 
     if (rd != 0) {
@@ -205,8 +218,19 @@ void HELPER(iremu128)(CPURISCVState *env, uint64_t rd,
         rl = ul;
         rh = uh;
     } else {
+#ifdef HARD_128BIT
+        /* If available, use builtin 128-bit type */
+        __uint128_t u = (((__uint128_t) uh) << 64) | ul,
+                    v = (((__uint128_t) vh) << 64) | vl,
+                    r;
+
+        r = u % v;
+        rl = r & 0xffffffffffffffff;
+        rh = (r >> 64) & 0xffffffffffffffff;
+#else
         /* Soft quad division */
         divmod128(ul, uh, vl, vh, NULL, NULL, &rl, &rh);
+#endif
     }
 
     if (rd != 0) {
@@ -216,6 +240,7 @@ void HELPER(iremu128)(CPURISCVState *env, uint64_t rd,
     return;
 }
 
+#ifndef HARD_128BIT
 static void neg128(uint64_t *valh, uint64_t *vall)
 {
     uint64_t oneh = ~(*valh), onel = ~(*vall);
@@ -223,6 +248,7 @@ static void neg128(uint64_t *valh, uint64_t *vall)
     /* Carry into upper 64 bits */
     *valh = (*vall < onel) ? oneh + 1 : oneh;
 }
+#endif
 
 void HELPER(idivs128)(CPURISCVState *env, uint64_t rd,
                       uint64_t ul, uint64_t uh,
@@ -238,6 +264,16 @@ void HELPER(idivs128)(CPURISCVState *env, uint64_t rd,
         ql = ul;
         qh = uh;
     } else {
+#ifdef HARD_128BIT
+        /* Use gcc's builtin 128 bit type */
+        __int128_t u = (__int128_t) ((((__uint128_t) uh) << 64) | ul),
+                   v = (__int128_t) ((((__uint128_t) vh) << 64) | vl);
+
+        __int128_t r = u / v;
+
+        ql = r & 0xffffffffffffffff;
+        qh = (r >> 64) & 0xffffffffffffffff;
+#else
         /* User unsigned divmod to build signed quotient */
         bool sgnu = (uh & 0x8000000000000000),
              sgnv = (vh & 0x8000000000000000);
@@ -255,6 +291,7 @@ void HELPER(idivs128)(CPURISCVState *env, uint64_t rd,
         if (sgnu != sgnv) {
             neg128(&qh, &ql);
         }
+#endif
     }
 
     if (rd != 0) {
@@ -273,6 +310,16 @@ void HELPER(irems128)(CPURISCVState *env, uint64_t rd,
         rl = ul;
         rh = uh;
     } else {
+#ifdef HARD_128BIT
+        /* Use gcc's builtin 128 bit type */
+        __int128_t u = (__int128_t) ((((__uint128_t) uh) << 64) | ul),
+                   v = (__int128_t) ((((__uint128_t) vh) << 64) | vl);
+
+        __int128_t r = u % v;
+
+        rl = r & 0xffffffffffffffff;
+        rh = (r >> 64) & 0xffffffffffffffff;
+#else
         /* User unsigned divmod to build signed remainder */
         bool sgnu = (uh & 0x8000000000000000),
              sgnv = (vh & 0x8000000000000000);
@@ -290,6 +337,7 @@ void HELPER(irems128)(CPURISCVState *env, uint64_t rd,
         if (sgnu) {
             neg128(&rh, &rl);
         }
+#endif
     }
 
     if (rd != 0) {
-- 
2.33.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]