[Top] [All Lists]

Re: Changing the treatment of the MIPS HI and LO registers

To: "Maciej W. Rozycki" <>, Ralf Baechle <>,,,
Subject: Re: Changing the treatment of the MIPS HI and LO registers
From: Maxim Kuvyrkov <>
Date: Wed, 11 Jun 2008 22:41:25 +0400
In-reply-to: <87zlpuxqfb.fsf@firetop.home>
Original-recipient: rfc822;
References: <87tzgj4nh6.fsf@firetop.home> <> <87abib4d9t.fsf@firetop.home> <> <87r6bm1ebd.fsf@firetop.home> <> <878wxtvarg.fsf@firetop.home> <8763stz2p3.fsf@firetop.home> <87zlpuxqfb.fsf@firetop.home>
User-agent: Thunderbird (Macintosh/20080421)
Richard Sandiford wrote:


+    <li>The MIPS port no longer recognizes the <code>h</code>
+    <code>asm</code> constraint.  It was necessary to remove
+    this constraint in order to avoid generating unpredictable
+    code sequences.
+    <p>One of the main uses of the <code>h</code> constraint
+    was to extract the high part of a multiplication on
+    64-bit targets.  For example:</p>
+    <pre>
+    asm ("dmultu\t%1,%2" : "=h" (result) : "r" (x), "r" (y));</pre>
+    <p>You can now achieve the same effect using 128-bit types:</p>
+    <pre>
+    typedef unsigned int uint128_t __attribute__((mode(TI)));
+    result = ((uint128_t) x * y) >> 64;</pre>
+    <p>The second sequence is better in many ways.  For example,
+    if <code>x</code> and <code>y</code> are constants, the
+    compiler can perform the multiplication at compile time.
+    If <code>x</code> and <code>y</code> are not constants,
+    the compiler can schedule the runtime multiplication
+    better than it can schedule an <code>asm</code> statement.</p>
+    </li>


GLIBC contains the following code in stdlib/longlong.h:
#if defined (__mips__) && W_TYPE_SIZE == 32
#define umul_ppmm(w1, w0, u, v) \
  __asm__ ("multu %2,%3"                                              \
           : "=l" ((USItype) (w0)),                                   \
             "=h" ((USItype) (w1))                                    \
           : "d" ((USItype) (u)),                                     \
             "d" ((USItype) (v)))
#define UMUL_TIME 10
#define UDIV_TIME 100
#endif /* __mips__ */

What would be a correct fix in this case?  Something like this:
#define umul_ppmm(w1, w0, u, v)                                 \
  ({unsigned int __attribute__((mode(DI))) __xx;                \
    __xx = (unsigned int __attribute__((mode(DI)))) u * v;      \
    w0 = __xx & ((1 << 32) - 1);                              \
    w1 = __xx >> 32;})

Or is there a better way?



<Prev in Thread] Current Thread [Next in Thread>