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>
</ul>
Hi,
GLIBC contains the following code in stdlib/longlong.h:
<snip>
#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__ */
</snip>
What would be a correct fix in this case? Something like this:
<snip>
#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;})
</snip>
Or is there a better way?
Thanks,
Maxim
|