On Tue, 24 Feb 2009, David Daney wrote: > @@ -16,4 +16,11 @@ > #define GCC_REG_ACCUM "accum" > #endif > > +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) > +#define GCC_NO_H_CONSTRAINT > +#ifdef CONFIG_64BIT > +typedef unsigned int uint128_t __attribute__((mode(TI))); > +#endif > +#endif > + > #endif /* _ASM_COMPILER_H */ I suggest to call it u128 in line with all the other such types (and place it in <asm/types.h>?). Also it might be more reasonable to call the macro something like GCC_HAS_EXT64_MULT or suchlike as in my opinion we should prefer using C code for a calculation like this even if the "h" constraint still worked. We might want to have i128 too. :) > @@ -62,8 +62,9 @@ static inline void __delay(unsigned long loops) > > static inline void __udelay(unsigned long usecs, unsigned long lpj) > { > +#ifndef GCC_NO_H_CONSTRAINT > unsigned long hi, lo; > - > +#endif > /* > * The rates of 128 is rounded wrongly by the catchall case > * for 64-bit. Excessive precission? Probably ... > @@ -77,6 +78,12 @@ static inline void __udelay(unsigned long usecs, unsigned long lpj) > 0x80000000ULL) >> 32); > #endif > > +#ifdef GCC_NO_H_CONSTRAINT > + if (sizeof(long) == 4) > + usecs = ((u64)usecs * lpj) >> 32; > + else > + usecs = ((uint128_t)usecs * lpj) >> 64; > +#else > if (sizeof(long) == 4) > __asm__("multu\t%2, %3" > : "=h" (usecs), "=l" (lo) > @@ -92,6 +99,7 @@ static inline void __udelay(unsigned long usecs, unsigned long lpj) > : "=r" (usecs), "=h" (hi), "=l" (lo) > : "r" (usecs), "r" (lpj) > : GCC_REG_ACCUM); > +#endif > > __delay(usecs); > } Ouch, this is horribly ugly. It begs for making the conditional chunks a pair of separate static inline functions. You could then do something like __delay(__usecs_to_loops(usecs, lpj)) and simply have two variants of __usecs_to_loops() with no need to chop code with #ifdefs in the middle. Maciej