diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7334de8e..0fa66d10 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,6 +31,8 @@ add_library(dynarmic common/sm4.cpp common/sm4.h common/string_util.h + common/u128.cpp + common/u128.h common/variant_util.h frontend/A32/decoder/arm.h frontend/A32/decoder/thumb16.h diff --git a/src/common/u128.cpp b/src/common/u128.cpp new file mode 100644 index 00000000..5d97d222 --- /dev/null +++ b/src/common/u128.cpp @@ -0,0 +1,64 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2018 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#include + +#include "common/common_types.h" +#include "common/u128.h" + +namespace Dynarmic { + +u128 operator<<(u128 operand, int amount) { + if (amount < 0) { + return operand >> -amount; + } + + if (amount == 0) { + return operand; + } + + if (amount < 64) { + u128 result; + result.lower = (operand.lower << amount); + result.upper = (operand.upper << amount) | (operand.lower >> (64 - amount)); + return result; + } + + if (amount < 128) { + u128 result; + result.upper = operand.lower << (amount - 64); + return result; + } + + return {}; +} + +u128 operator>>(u128 operand, int amount) { + if (amount < 0) { + return operand << -amount; + } + + if (amount == 0) { + return operand; + } + + if (amount < 64) { + u128 result; + result.lower = (operand.lower >> amount) | (operand.upper << (64 - amount)); + result.upper = (operand.upper >> amount); + return result; + } + + if (amount < 128) { + u128 result; + result.lower = operand.upper >> (amount - 64); + return result; + } + + return {}; +} + +} // namespace Dynarmic diff --git a/src/common/u128.h b/src/common/u128.h new file mode 100644 index 00000000..b08143c8 --- /dev/null +++ b/src/common/u128.h @@ -0,0 +1,57 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2018 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#pragma once + +#include +#include + +#include "common/bit_util.h" +#include "common/common_types.h" + +namespace Dynarmic { + +struct u128 { + u128() = default; + u128(const u128&) = default; + u128(u128&&) = default; + u128& operator=(const u128&) = default; + u128& operator=(u128&&) = default; + + u128(u64 lower_, u64 upper_) : lower(lower_), upper(upper_) {} + + template + /* implicit */ u128(T value) : lower(value), upper(0) { + static_assert(std::is_integral_v); + static_assert(Common::BitSize() <= Common::BitSize()); + } + + u64 lower = 0; + u64 upper = 0; +}; + +static_assert(Common::BitSize() == 128); +static_assert(std::is_standard_layout_v); +static_assert(std::is_trivially_copyable_v); + +inline u128 operator+(u128 a, u128 b) { + u128 result; + result.lower = a.lower + b.lower; + result.upper = a.upper + b.upper + (a.lower > result.lower); + return result; +} + +inline u128 operator-(u128 a, u128 b) { + u128 result; + result.lower = a.lower - b.lower; + result.upper = a.upper - b.upper - (a.lower < result.lower); + return result; +} + +u128 operator<<(u128 operand, int amount); +u128 operator>>(u128 operand, int amount); + +} // namespace Dynarmic