uint128.cpp 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. // Copyright 2019 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #ifdef _MSC_VER
  5. #include <intrin.h>
  6. #pragma intrinsic(_umul128)
  7. #endif
  8. #include <cstring>
  9. #include "common/uint128.h"
  10. namespace Common {
  11. u128 Multiply64Into128(u64 a, u64 b) {
  12. u128 result;
  13. #ifdef _MSC_VER
  14. result[0] = _umul128(a, b, &result[1]);
  15. #else
  16. unsigned __int128 tmp = a;
  17. tmp *= b;
  18. std::memcpy(&result, &tmp, sizeof(u128));
  19. #endif
  20. return result;
  21. }
  22. std::pair<u64, u64> Divide128On32(u128 dividend, u32 divisor) {
  23. u64 remainder = dividend[0] % divisor;
  24. u64 accum = dividend[0] / divisor;
  25. if (dividend[1] == 0)
  26. return {accum, remainder};
  27. // We ignore dividend[1] / divisor as that overflows
  28. const u64 first_segment = (dividend[1] % divisor) << 32;
  29. accum += (first_segment / divisor) << 32;
  30. const u64 second_segment = (first_segment % divisor) << 32;
  31. accum += (second_segment / divisor);
  32. remainder += second_segment % divisor;
  33. if (remainder >= divisor) {
  34. accum++;
  35. remainder -= divisor;
  36. }
  37. return {accum, remainder};
  38. }
  39. } // namespace Common