/*************************************************
* MPI Multiply-Add Core Header File              *
* (C) 1999-2005 The Botan Project                *
*************************************************/

#ifndef BOTAN_MP_MADD_H__
#define BOTAN_MP_MADD_H__

#include <botan/mp_core.h>

namespace Botan {

/*************************************************
* Multiply-Add Operation                         *
*************************************************/
inline void bigint_madd(word a, word b, word c, word d,
                        word* out_low, word* out_high)
   {
#if (BOTAN_MP_WORD_BITS != 64)
   #error The mp_asm64 module requires that BOTAN_MP_WORD_BITS == 64
#endif

   word z0 = 0, z1 = 0;

#if defined(__GNUC__)

#if defined(BOTAN_TARGET_ARCH_IS_ALPHA)
   asm("umulh %1,%2,%0" : "=r" (z0) : "r" (a), "r" (b));
   z1 = a * b;
#elif defined(BOTAN_TARGET_ARCH_IS_IA64)
   asm("xmpy.hu %0=%1,%2" : "=f" (z0) : "f" (a), "f" (b));
   z1 = a * b;
#elif defined(BOTAN_TARGET_ARCH_IS_PPC64)
   asm("mulhdu %0,%1,%2" : "=r" (z0) : "r" (a), "r" (b) : "cc");
   z1 = a * b;
#elif defined(BOTAN_TARGET_ARCH_IS_AMD64)
   asm("mulq %3" : "=d" (z0), "=a" (z1) : "a" (a), "rm" (b) : "cc");
#elif defined(BOTAN_TARGET_ARCH_IS_MIPS64)
   asm("dmultu %2,%3" : "=h" (z0), "=l" (z1) : "r" (a), "r" (b));
#else
   bigint_wordmul(a, b, &z1, &z0);
#endif

#else
   bigint_wordmul(a, b, &z1, &z0);
#endif

   z1 += c; if(z1 < c) z0++;
   z1 += d; if(z1 < d) z0++;

   *out_low = z1;
   *out_high = z0;
   }

}

#endif
