u128: Add Multiply64To128
This commit is contained in:
parent
5566fab29a
commit
b0afd53ea7
2 changed files with 33 additions and 0 deletions
|
@ -11,6 +11,37 @@
|
||||||
|
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
|
|
||||||
|
u128 Multiply64To128(u64 a, u64 b) {
|
||||||
|
const u32 a0 = static_cast<u32>(a);
|
||||||
|
const u32 b0 = static_cast<u32>(b);
|
||||||
|
const u32 a1 = static_cast<u32>(a >> 32);
|
||||||
|
const u32 b1 = static_cast<u32>(b >> 32);
|
||||||
|
|
||||||
|
// result = (c2 << 64) + (c1 << 32) + c0
|
||||||
|
// c2 = a1 * b1
|
||||||
|
// c1 = a1 * b0 + a0 * b1
|
||||||
|
// c0 = a0 * b0
|
||||||
|
// noting that these operations may overflow
|
||||||
|
|
||||||
|
const u64 c0 = static_cast<u64>(a0) * b0;
|
||||||
|
const u64 c1_0 = static_cast<u64>(a1) * b0;
|
||||||
|
const u64 c1_1 = static_cast<u64>(a0) * b1;
|
||||||
|
const u64 c2 = static_cast<u64>(a1) * b1;
|
||||||
|
|
||||||
|
const u64 c1 = c1_0 + c1_1;
|
||||||
|
const u64 c1_overflow = c1 < c1_0;
|
||||||
|
|
||||||
|
const u64 lower = c0 + (c1 << 32);
|
||||||
|
const u64 lower_overflow = lower < c0;
|
||||||
|
|
||||||
|
const u64 upper = lower_overflow + (c1 >> 32) + (c1_overflow << 32) + c2;
|
||||||
|
|
||||||
|
u128 result;
|
||||||
|
result.lower = lower;
|
||||||
|
result.upper = upper;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
u128 operator<<(u128 operand, int amount) {
|
u128 operator<<(u128 operand, int amount) {
|
||||||
if (amount < 0) {
|
if (amount < 0) {
|
||||||
return operand >> -amount;
|
return operand >> -amount;
|
||||||
|
|
|
@ -48,6 +48,8 @@ static_assert(Common::BitSize<u128>() == 128);
|
||||||
static_assert(std::is_standard_layout_v<u128>);
|
static_assert(std::is_standard_layout_v<u128>);
|
||||||
static_assert(std::is_trivially_copyable_v<u128>);
|
static_assert(std::is_trivially_copyable_v<u128>);
|
||||||
|
|
||||||
|
u128 Multiply64To128(u64 a, u64 b);
|
||||||
|
|
||||||
inline u128 operator+(u128 a, u128 b) {
|
inline u128 operator+(u128 a, u128 b) {
|
||||||
u128 result;
|
u128 result;
|
||||||
result.lower = a.lower + b.lower;
|
result.lower = a.lower + b.lower;
|
||||||
|
|
Loading…
Reference in a new issue