osd: 64x64 multiply helpers (nw)

Can we have these? I didn't attempt to add implementations for anything other than MSVC, but I believe gcc and clang for 64-bit targets have equivalents.
This commit is contained in:
Patrick Mackinlay 2019-02-13 11:49:31 +07:00 committed by Vas Crabb
parent b113d0c26d
commit a7c5845317
2 changed files with 76 additions and 0 deletions

View File

@ -403,4 +403,24 @@ static inline float _recip_approx(float z)
}
#endif
/*-------------------------------------------------
mul_64x64 - perform a signed 64 bit x 64 bit
multiply and return the full 128 bit result
-------------------------------------------------*/
#ifdef PTR64
#define mul_64x64 _mul128
#endif
/*-------------------------------------------------
mulu_64x64 - perform an unsigned 64 bit x 64
bit multiply and return the full 128 bit result
-------------------------------------------------*/
#ifdef PTR64
#define mulu_64x64 _umul128
#endif
#endif // MAME_OSD_EIVCX86_H

View File

@ -260,6 +260,62 @@ inline float recip_approx(float value)
#endif
/*-------------------------------------------------
mul_64x64 - perform a signed 64 bit x 64 bit
multiply and return the full 128 bit result
-------------------------------------------------*/
#ifndef mul_64x64
inline int64_t mul_64x64(int64_t a, int64_t b, int64_t *hi)
{
uint64_t const a_hi = uint32_t(a >> 32);
uint64_t const b_hi = uint32_t(b >> 32);
uint64_t const a_lo = uint32_t(a);
uint64_t const b_lo = uint32_t(b);
uint64_t const ab_lo = a_lo * b_lo;
uint64_t const ab_m1 = a_hi * b_lo;
uint64_t const ab_m2 = a_lo * b_hi;
uint64_t const ab_hi = a_hi * b_hi;
uint64_t const carry = ((ab_lo >> 32) + uint32_t(ab_m1) + uint32_t(ab_m2)) >> 32;
*hi = ab_hi + (ab_m1 >> 32) + (ab_m2 >> 32) + carry;
// adjust for sign
if (a < 0)
*hi -= b;
if (b < 0)
*hi -= a;
return ab_lo + (ab_m1 << 32) + (ab_m2 << 32);
}
#endif
/*-------------------------------------------------
mulu_64x64 - perform an unsigned 64 bit x 64
bit multiply and return the full 128 bit result
-------------------------------------------------*/
#ifndef mulu_64x64
inline uint64_t mulu_64x64(uint64_t a, uint64_t b, uint64_t *hi)
{
uint64_t const a_hi = uint32_t(a >> 32);
uint64_t const b_hi = uint32_t(b >> 32);
uint64_t const a_lo = uint32_t(a);
uint64_t const b_lo = uint32_t(b);
uint64_t const ab_lo = a_lo * b_lo;
uint64_t const ab_m1 = a_hi * b_lo;
uint64_t const ab_m2 = a_lo * b_hi;
uint64_t const ab_hi = a_hi * b_hi;
uint64_t const carry = ((ab_lo >> 32) + uint32_t(ab_m1) + uint32_t(ab_m2)) >> 32;
*hi = ab_hi + (ab_m1 >> 32) + (ab_m2 >> 32) + carry;
return ab_lo + (ab_m1 << 32) + (ab_m2 << 32);
}
#endif
/***************************************************************************
INLINE BIT MANIPULATION FUNCTIONS