summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/eminline.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/eminline.h')
-rw-r--r--src/osd/eminline.h58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/osd/eminline.h b/src/osd/eminline.h
index bb0aec63468..eb8ffaa9748 100644
--- a/src/osd/eminline.h
+++ b/src/osd/eminline.h
@@ -260,6 +260,64 @@ 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 = uint64_t(a) >> 32;
+ uint64_t const b_hi = uint64_t(b) >> 32;
+ uint64_t const a_lo = uint32_t(uint64_t(a));
+ uint64_t const b_lo = uint32_t(uint64_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