diff mbox series

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

Message ID 20210830171638.126325-6-frederic.petrot@univ-grenoble-alpes.fr
State New
Headers show
Series [1/8] target/riscv: Settings for 128-bit extension support | expand

Commit Message

Frédéric Pétrot Aug. 30, 2021, 5:16 p.m. UTC
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(+)

Comments

Richard Henderson Aug. 31, 2021, 3:38 a.m. UTC | #1
On 8/30/21 10:16 AM, Frédéric Pétrot wrote:
> 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

This doesn't belong here.  CONFIG_INT128 is more correct.


r~
diff mbox series

Patch

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) {