diff mbox series

[PULL,8/8] softfloat: Specialize udiv_qrnnd for ppc64

Message ID 20181005180201.11387-9-richard.henderson@linaro.org
State Accepted
Commit 27ae5109a2ba8b6b679cce3e03e16570a34390a0
Headers show
Series softfloat queue | expand

Commit Message

Richard Henderson Oct. 5, 2018, 6:02 p.m. UTC
The ISA has a 128/64-bit division instruction, though it assumes the
low 64-bits of the numerator are 0, and so requires a bit more fixup
than a full 128-bit division insn.

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
 include/fpu/softfloat-macros.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

-- 
2.17.1

Comments

Laurent Vivier Oct. 31, 2018, 6:46 p.m. UTC | #1
On 05/10/2018 20:02, Richard Henderson wrote:
> The ISA has a 128/64-bit division instruction, though it assumes the

> low 64-bits of the numerator are 0, and so requires a bit more fixup

> than a full 128-bit division insn.

> 

> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

> ---

>  include/fpu/softfloat-macros.h | 16 ++++++++++++++++

>  1 file changed, 16 insertions(+)

> 

> diff --git a/include/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h

> index eafc68932b..c86687fa5e 100644

> --- a/include/fpu/softfloat-macros.h

> +++ b/include/fpu/softfloat-macros.h

> @@ -647,6 +647,22 @@ static inline uint64_t udiv_qrnnd(uint64_t *r, uint64_t n1,

>      asm("dlgr %0, %1" : "+r"(n) : "r"(d));

>      *r = n >> 64;

>      return n;

> +#elif defined(_ARCH_PPC64)

> +    /* From Power ISA 3.0B, programming note for divdeu.  */

> +    uint64_t q1, q2, Q, r1, r2, R;

> +    asm("divdeu %0,%2,%4; divdu %1,%3,%4"

> +        : "=&r"(q1), "=r"(q2)

> +        : "r"(n1), "r"(n0), "r"(d));

> +    r1 = -(q1 * d);         /* low part of (n1<<64) - (q1 * d) */

> +    r2 = n0 - (q2 * d);

> +    Q = q1 + q2;

> +    R = r1 + r2;

> +    if (R >= d || R < r2) { /* overflow implies R > d */

> +        Q += 1;

> +        R -= d;

> +    }

> +    *r = R;

> +    return Q;

>  #else

>      uint64_t d0, d1, q0, q1, r1, r0, m;

>  

> 


This breaks qemu-s390x (and probably some others) on PPC64.

sudo chroot chroot/s390x/stretch/ apt-get update --yes
Ign:1 http://ftp.de.debian.org/debian stretch InRelease
Hit:2 http://ftp.de.debian.org/debian stretch Release
0% [Working]Illegal instruction

I didn't find any relevant information with "QEMU_STRACE=
QEMU_SINGLESTEP= QEMU_LOG=in_asm,op,unimp,int"

I will try to add some traces manually.

Thanks,
Laurent
Laurent Vivier Nov. 1, 2018, 5:01 p.m. UTC | #2
On 31/10/2018 19:46, Laurent Vivier wrote:
> On 05/10/2018 20:02, Richard Henderson wrote:

>> The ISA has a 128/64-bit division instruction, though it assumes the

>> low 64-bits of the numerator are 0, and so requires a bit more fixup

>> than a full 128-bit division insn.

>>

>> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

>> ---

>>  include/fpu/softfloat-macros.h | 16 ++++++++++++++++

>>  1 file changed, 16 insertions(+)

>>

>> diff --git a/include/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h

>> index eafc68932b..c86687fa5e 100644

>> --- a/include/fpu/softfloat-macros.h

>> +++ b/include/fpu/softfloat-macros.h

>> @@ -647,6 +647,22 @@ static inline uint64_t udiv_qrnnd(uint64_t *r, uint64_t n1,

>>      asm("dlgr %0, %1" : "+r"(n) : "r"(d));

>>      *r = n >> 64;

>>      return n;

>> +#elif defined(_ARCH_PPC64)

>> +    /* From Power ISA 3.0B, programming note for divdeu.  */


So it fails because my PowerMac G5 is not Power ISA 3.0B...

Something like this fixes the problem. I'm not sure it's the cleanest way:

diff --git a/include/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h
index c86687fa5e..5a724da2ea 100644
--- a/include/fpu/softfloat-macros.h
+++ b/include/fpu/softfloat-macros.h
@@ -79,6 +79,10 @@ this code that are retained.
  * version 2 or later. See the COPYING file in the top-level directory.
  */

+#if defined(_ARCH_PPC64)
+extern bool have_isa_3_00;
+#endif
+
 /*----------------------------------------------------------------------------
 | Shifts `a' right by the number of bits given in `count'.  If any nonzero
 | bits are shifted off, they are ``jammed'' into the least significant
bit of
@@ -647,7 +651,9 @@ static inline uint64_t udiv_qrnnd(uint64_t *r,
uint64_t n1,
     asm("dlgr %0, %1" : "+r"(n) : "r"(d));
     *r = n >> 64;
     return n;
-#elif defined(_ARCH_PPC64)
+#else
+#if defined(_ARCH_PPC64)
+    if (have_isa_3_00) {
         /* From Power ISA 3.0B, programming note for divdeu.  */
         uint64_t q1, q2, Q, r1, r2, R;
         asm("divdeu %0,%2,%4; divdu %1,%3,%4"
@@ -663,7 +669,8 @@ static inline uint64_t udiv_qrnnd(uint64_t *r,
uint64_t n1,
         }
         *r = R;
         return Q;
-#else
+    }
+#endif
     uint64_t d0, d1, q0, q1, r1, r0, m;

     d0 = (uint32_t)d;

Thanks,
Laurent
diff mbox series

Patch

diff --git a/include/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h
index eafc68932b..c86687fa5e 100644
--- a/include/fpu/softfloat-macros.h
+++ b/include/fpu/softfloat-macros.h
@@ -647,6 +647,22 @@  static inline uint64_t udiv_qrnnd(uint64_t *r, uint64_t n1,
     asm("dlgr %0, %1" : "+r"(n) : "r"(d));
     *r = n >> 64;
     return n;
+#elif defined(_ARCH_PPC64)
+    /* From Power ISA 3.0B, programming note for divdeu.  */
+    uint64_t q1, q2, Q, r1, r2, R;
+    asm("divdeu %0,%2,%4; divdu %1,%3,%4"
+        : "=&r"(q1), "=r"(q2)
+        : "r"(n1), "r"(n0), "r"(d));
+    r1 = -(q1 * d);         /* low part of (n1<<64) - (q1 * d) */
+    r2 = n0 - (q2 * d);
+    Q = q1 + q2;
+    R = r1 + r2;
+    if (R >= d || R < r2) { /* overflow implies R > d */
+        Q += 1;
+        R -= d;
+    }
+    *r = R;
+    return Q;
 #else
     uint64_t d0, d1, q0, q1, r1, r0, m;