/* $Id: level0.h,v 1.1.1.1 1999/09/16 13:47:46 karim Exp $ */
/* This file defines some "level 0" kernel functions for Intel x386 */
/* It is intended for use with an external "asm" definition */
#ifndef ASMINLINE
#define LOCAL_OVERFLOW
#define SAVE_OVERFLOW
#define LOCAL_HIREMAINDER
#define SAVE_HIREMAINDER
BEGINEXTERN
extern ulong overflow;
extern ulong hiremainder;
extern long addll(ulong x, ulong y);
extern long addllx(ulong x, ulong y);
extern long subll(ulong x, ulong y);
extern long subllx(ulong x, ulong y);
extern long shiftl(ulong x, ulong y);
extern long shiftlr(ulong x, ulong y);
extern long mulll(ulong x, ulong y);
extern long addmul(ulong x, ulong y);
extern long divll(ulong x, ulong y);
extern int bfffo(ulong x);
ENDEXTERN
#else /* ASMINLINE */
/* $Id: level0.h,v 1.1.1.1 1999/09/16 13:47:46 karim Exp $ */
/* Written by Bruno Haible, 1996-1998. */
/* This file can assume the GNU C extensions.
(It is included only if __GNUC__ is defined.) */
/* Use local variables whenever possible. */
#define LOCAL_HIREMAINDER register unsigned long hiremainder
#define SAVE_OVERFLOW \
{ unsigned long _temp_overf = overflow; \
extern unsigned long overflow; \
overflow = _temp_overf; }
#define LOCAL_OVERFLOW unsigned long overflow
#define SAVE_HIREMAINDER \
{ unsigned long _temp_hirem = hiremainder; \
extern unsigned long hiremainder; \
hiremainder = _temp_hirem; }
/* The global variable `hiremainder' is still necessary for the 2nd value of
divss, divis, divsi. The global variable `overflow' is not necessary. */
extern ulong overflow;
extern ulong hiremainder;
/* Different assemblers have different syntax for the "shldl" and "shrdl"
instructions. */
#if defined(__EMX__) || defined(__DJGCC__) || defined(__GO32__) || (defined(linux) && !defined(__ELF__)) || defined(__386BSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(NeXT) || defined(__CYGWIN32__) || defined(__MINGW32__) || defined(COHERENT)
# define SHCL "%%cl,"
#else
# define SHCL
#endif
#define addll(a,b) \
({ unsigned long __value, __arg1 = (a), __arg2 = (b); \
__asm__ ("addl %3,%0 ; adcl %1,%1" \
: "=r" (__value), "=r" (overflow) \
: "0" (__arg1), "g" (__arg2), "1" ((unsigned long)0) \
: "cc"); \
__value; \
})
#define addllx(a,b) \
({ unsigned long __value, __arg1 = (a), __arg2 = (b), __temp; \
__asm__ ("subl %5,%2 ; adcl %4,%0 ; adcl %1,%1" \
: "=r" (__value), "=r" (overflow), "=r" (__temp) \
: "0" (__arg1), "g" (__arg2), "g" (overflow), "1" ((unsigned long)0), "2" ((unsigned long)0) \
: "cc"); \
__value; \
})
#define subll(a,b) \
({ unsigned long __value, __arg1 = (a), __arg2 = (b); \
__asm__ ("subl %3,%0 ; adcl %1,%1" \
: "=r" (__value), "=r" (overflow) \
: "0" (__arg1), "g" (__arg2), "1" ((unsigned long)0) \
: "cc"); \
__value; \
})
#define subllx(a,b) \
({ unsigned long __value, __arg1 = (a), __arg2 = (b), __temp; \
__asm__ ("subl %5,%2 ; sbbl %4,%0 ; adcl %1,%1" \
: "=r" (__value), "=r" (overflow), "=r" (__temp) \
: "0" (__arg1), "g" (__arg2), "g" (overflow), "1" ((unsigned long)0), "2" ((unsigned long)0) \
: "cc"); \
__value; \
})
#if 1
#define shiftl(a,c) \
({ unsigned long __valuelo = (a), __count = (c), __valuehi; \
__asm__ ("shldl "SHCL"%2,%0" /* shift %0 left by %cl bits, feeding in %2 from the right */ \
: "=q" (__valuehi) \
: "0" ((unsigned long)0), "q" (__valuelo), "c" /* %ecx */ (__count)); \
hiremainder = __valuehi; \
__valuelo << __count; \
})
#define shiftlr(a,c) \
({ unsigned long __valuehi = (a), __count = (c), __valuelo; \
__asm__ ("shrdl "SHCL"%2,%0" /* shift %0 right by %cl bits, feeding in %2 from the left */ \
: "=q" (__valuelo) \
: "0" ((unsigned long)0), "q" (__valuehi), "c" /* %ecx */ (__count)); \
hiremainder = __valuelo; \
__valuehi >> __count; \
})
#else
#define shiftl(a,c) \
({ unsigned long __valuelo = (a), __count = (c), __valuehi; \
__asm__ ("shldl "SHCL"%2,%0" /* shift %0 left by %cl bits, feeding in %2 from the right */ \
: "=d" (hiremainder) \
: "0" ((unsigned long)0), "q" (__valuelo), "c" /* %ecx */ (__count)); \
__valuelo << __count; \
})
#define shiftlr(a,c) \
({ unsigned long __valuehi = (a), __count = (c), __valuelo; \
__asm__ ("shrdl "SHCL"%2,%0" /* shift %0 right by %cl bits, feeding in %2 from the left */ \
: "=d" (hiremainder) \
: "0" ((unsigned long)0), "q" (__valuehi), "c" /* %ecx */ (__count)); \
__valuehi >> __count; \
})
#endif
#define mulll(a,b) \
({ unsigned long __valuelo, __arg1 = (a), __arg2 = (b); \
__asm__ ("mull %3" \
: "=a" /* %eax */ (__valuelo), "=d" /* %edx */ (hiremainder) \
: "0" (__arg1), "rm" (__arg2)); \
__valuelo; \
})
#define addmul(a,b) \
({ unsigned long __valuelo, __arg1 = (a), __arg2 = (b), __temp; \
__asm__ ("mull %4 ; addl %5,%0 ; adcl %6,%1" \
: "=a" /* %eax */ (__valuelo), "=&d" /* %edx */ (hiremainder), "=r" (__temp) \
: "0" (__arg1), "rm" (__arg2), "g" (hiremainder), "2" ((unsigned long)0)); \
__valuelo; \
})
#define addmullow(a,b) \
({ unsigned long __valuelo, __arg1 = (a), __arg2 = (b), __temp; \
__asm__ ("mull %3 ; addl %4,%0" \
: "=a" /* %eax */ (__valuelo), "=&d" /* %edx */ (__temp) \
: "0" (__arg1), "rm" (__arg2), "g" (hiremainder)); \
__valuelo; \
})
#define divll(a,b) \
({ unsigned long __value, __arg1 = (a), __arg2 = (b); \
__asm__ ("divl %4" \
: "=a" /* %eax */ (__value), "=d" /* %edx */ (hiremainder) \
: "0" /* %eax */ (__arg1), "1" /* %edx */ (hiremainder), "g" (__arg2)); \
__value; \
})
#ifndef _ASMI386INLINE_H_
# define _ASMI386INLINE_H_
# ifdef INLINE
static inline int
bfffo(unsigned long x)
{
int leading_one_position;
__asm__ ("bsrl %1,%0" : "=r" (leading_one_position) : "rm" (x));
return 31-leading_one_position;
}
# endif
#endif
#endif /* ASMINLINE */