mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 14:47:46 +00:00
LibX86: Add basic u128 and u256 constainers
These support all bitwise operations
This commit is contained in:
parent
fa59d02692
commit
a99812633b
5 changed files with 660 additions and 0 deletions
|
@ -1,5 +1,6 @@
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
Instruction.cpp
|
Instruction.cpp
|
||||||
|
Types/Formatter.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
serenity_lib(LibX86 x86)
|
serenity_lib(LibX86 x86)
|
||||||
|
|
10
Userland/Libraries/LibX86/Types.h
Normal file
10
Userland/Libraries/LibX86/Types.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Leon Albrecht <leon2002.la@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Types/u128.h"
|
||||||
|
#include "Types/u256.h"
|
113
Userland/Libraries/LibX86/Types/Formatter.cpp
Normal file
113
Userland/Libraries/LibX86/Types/Formatter.cpp
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Leon Albrecht <leon2002.la@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "u128.h"
|
||||||
|
#include "u256.h"
|
||||||
|
|
||||||
|
#include <AK/Format.h>
|
||||||
|
#include <AK/String.h>
|
||||||
|
#include <AK/StringBuilder.h>
|
||||||
|
#include <serenity.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void AK::Formatter<u128>::format(AK::FormatBuilder& builder, u128 value)
|
||||||
|
{
|
||||||
|
if (value.high() == 0) {
|
||||||
|
AK::Formatter<u64> formatter { *this };
|
||||||
|
return formatter.format(builder, value.low());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_precision.has_value())
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
|
||||||
|
if (m_mode == Mode::Pointer) {
|
||||||
|
// this is way to big for a pointer
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 base = 0;
|
||||||
|
bool upper_case = false;
|
||||||
|
if (m_mode == Mode::Binary) {
|
||||||
|
base = 2;
|
||||||
|
} else if (m_mode == Mode::BinaryUppercase) {
|
||||||
|
base = 2;
|
||||||
|
upper_case = true;
|
||||||
|
} else if (m_mode == Mode::Octal) {
|
||||||
|
base = 8;
|
||||||
|
} else if (m_mode == Mode::Decimal || m_mode == Mode::Default) {
|
||||||
|
// FIXME: implement this
|
||||||
|
TODO();
|
||||||
|
} else if (m_mode == Mode::Hexadecimal) {
|
||||||
|
base = 16;
|
||||||
|
} else if (m_mode == Mode::HexadecimalUppercase) {
|
||||||
|
base = 16;
|
||||||
|
upper_case = true;
|
||||||
|
} else {
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 lower_length = sizeof(u64) * 0xFF / base;
|
||||||
|
if (m_width.value() > lower_length) {
|
||||||
|
builder.put_u64(value.high(), base, m_alternative_form, upper_case, m_zero_pad, m_align, m_width.value() - lower_length, m_fill, m_sign_mode);
|
||||||
|
builder.put_u64(value.low(), base, false, upper_case, m_zero_pad, m_align, m_width.value(), m_fill, m_sign_mode);
|
||||||
|
} else {
|
||||||
|
builder.put_u64(value.low(), base, m_alternative_form, upper_case, m_zero_pad, m_align, m_width.value(), m_fill, m_sign_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AK::Formatter<u256>::format(AK::FormatBuilder& builder, u256 value)
|
||||||
|
{
|
||||||
|
if (value.high() == 0) {
|
||||||
|
AK::Formatter<u128> formatter { *this };
|
||||||
|
return formatter.format(builder, value.low());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_precision.has_value())
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
|
||||||
|
if (m_mode == Mode::Pointer) {
|
||||||
|
// this is way to big for a pointer
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 base = 0;
|
||||||
|
bool upper_case = false;
|
||||||
|
if (m_mode == Mode::Binary) {
|
||||||
|
base = 2;
|
||||||
|
} else if (m_mode == Mode::BinaryUppercase) {
|
||||||
|
base = 2;
|
||||||
|
upper_case = true;
|
||||||
|
} else if (m_mode == Mode::Octal) {
|
||||||
|
base = 8;
|
||||||
|
} else if (m_mode == Mode::Decimal || m_mode == Mode::Default) {
|
||||||
|
// FIXME: implement this
|
||||||
|
TODO();
|
||||||
|
} else if (m_mode == Mode::Hexadecimal) {
|
||||||
|
base = 16;
|
||||||
|
} else if (m_mode == Mode::HexadecimalUppercase) {
|
||||||
|
base = 16;
|
||||||
|
upper_case = true;
|
||||||
|
} else {
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 part_length = sizeof(u128) * 0xFF / base;
|
||||||
|
if (m_width.value() > part_length * 3) {
|
||||||
|
builder.put_u64(value.high().high(), base, m_alternative_form, upper_case, m_zero_pad, m_align, m_width.value() - part_length * 3, m_fill, m_sign_mode);
|
||||||
|
builder.put_u64(value.high().low(), base, false, upper_case, m_zero_pad, m_align, part_length, m_fill, m_sign_mode);
|
||||||
|
builder.put_u64(value.low().high(), base, false, upper_case, m_zero_pad, m_align, part_length, m_fill, m_sign_mode);
|
||||||
|
builder.put_u64(value.low().low(), base, false, upper_case, m_zero_pad, m_align, part_length, m_fill, m_sign_mode);
|
||||||
|
} else if (m_width.value() > part_length * 2) {
|
||||||
|
builder.put_u64(value.high().low(), base, m_alternative_form, upper_case, m_zero_pad, m_align, m_width.value() - part_length * 2, m_fill, m_sign_mode);
|
||||||
|
builder.put_u64(value.low().high(), base, false, upper_case, m_zero_pad, m_align, part_length, m_fill, m_sign_mode);
|
||||||
|
builder.put_u64(value.low().low(), base, false, upper_case, m_zero_pad, m_align, part_length, m_fill, m_sign_mode);
|
||||||
|
} else if (m_width.value() > part_length) {
|
||||||
|
builder.put_u64(value.low().high(), base, m_alternative_form, upper_case, m_zero_pad, m_align, m_width.value() - part_length, m_fill, m_sign_mode);
|
||||||
|
builder.put_u64(value.low().low(), base, false, upper_case, m_zero_pad, m_align, part_length, m_fill, m_sign_mode);
|
||||||
|
} else {
|
||||||
|
builder.put_u64(value.low().low(), base, m_alternative_form, upper_case, m_zero_pad, m_align, m_width.value(), m_fill, m_sign_mode);
|
||||||
|
}
|
||||||
|
}
|
268
Userland/Libraries/LibX86/Types/u128.h
Normal file
268
Userland/Libraries/LibX86/Types/u128.h
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Leon Albrecht <leon2002.la@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Concepts.h>
|
||||||
|
#include <AK/Format.h>
|
||||||
|
#include <AK/Types.h>
|
||||||
|
|
||||||
|
namespace X86 {
|
||||||
|
|
||||||
|
class u128 {
|
||||||
|
public:
|
||||||
|
constexpr u128() = default;
|
||||||
|
template<Unsigned T>
|
||||||
|
constexpr u128(T val)
|
||||||
|
: m_low(val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
constexpr u128(u64 val_low, u64 val_high)
|
||||||
|
: m_low(val_low)
|
||||||
|
, m_high(val_high)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE u8* bytes()
|
||||||
|
{
|
||||||
|
return m_bytes;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE const u8* bytes() const
|
||||||
|
{
|
||||||
|
return m_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE u16* words()
|
||||||
|
{
|
||||||
|
return (u16*)m_bytes;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE const u16* words() const
|
||||||
|
{
|
||||||
|
return (const u16*)m_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE u32* double_words()
|
||||||
|
{
|
||||||
|
return (u32*)m_bytes;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE const u32* double_words() const
|
||||||
|
{
|
||||||
|
return (const u32*)m_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE constexpr u64& low()
|
||||||
|
{
|
||||||
|
return m_low;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr const u64& low() const
|
||||||
|
{
|
||||||
|
return m_low;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE constexpr u64& high()
|
||||||
|
{
|
||||||
|
return m_high;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr const u64& high() const
|
||||||
|
{
|
||||||
|
return m_high;
|
||||||
|
}
|
||||||
|
|
||||||
|
// conversion
|
||||||
|
template<Unsigned T>
|
||||||
|
ALWAYS_INLINE constexpr operator T() const
|
||||||
|
{
|
||||||
|
return m_low;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE constexpr operator bool() const
|
||||||
|
{
|
||||||
|
return m_low || m_high;
|
||||||
|
}
|
||||||
|
|
||||||
|
// comparisons
|
||||||
|
template<Unsigned T>
|
||||||
|
ALWAYS_INLINE constexpr bool operator==(const T& other) const
|
||||||
|
{
|
||||||
|
return (!m_high) && m_low == other;
|
||||||
|
}
|
||||||
|
template<Unsigned T>
|
||||||
|
ALWAYS_INLINE constexpr bool operator!=(const T& other) const
|
||||||
|
{
|
||||||
|
return m_high || m_low != other;
|
||||||
|
}
|
||||||
|
template<Unsigned T>
|
||||||
|
ALWAYS_INLINE constexpr bool operator>(const T& other) const
|
||||||
|
{
|
||||||
|
return m_high || m_low > other;
|
||||||
|
}
|
||||||
|
template<Unsigned T>
|
||||||
|
ALWAYS_INLINE constexpr bool operator<(const T& other) const
|
||||||
|
{
|
||||||
|
return !m_high && m_low < other;
|
||||||
|
}
|
||||||
|
template<Unsigned T>
|
||||||
|
ALWAYS_INLINE constexpr bool operator>=(const T& other) const
|
||||||
|
{
|
||||||
|
return *this == other || *this > other;
|
||||||
|
}
|
||||||
|
template<Unsigned T>
|
||||||
|
ALWAYS_INLINE constexpr bool operator<=(const T& other) const
|
||||||
|
{
|
||||||
|
return *this == other || *this < other;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE constexpr bool operator==(const u128& other) const
|
||||||
|
{
|
||||||
|
return m_low == other.low() && m_high == other.high();
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr bool operator!=(const u128& other) const
|
||||||
|
{
|
||||||
|
return m_low != other.low() || m_high != other.high();
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr bool operator>(const u128& other) const
|
||||||
|
{
|
||||||
|
return m_high > other.high()
|
||||||
|
|| (m_high == other.high() && m_low > other.low());
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr bool operator<(const u128& other) const
|
||||||
|
{
|
||||||
|
return m_high < other.high()
|
||||||
|
|| (m_high == other.high() && m_low < other.low());
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr bool operator>=(const u128& other) const
|
||||||
|
{
|
||||||
|
return *this == other || *this > other;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr bool operator<=(const u128& other) const
|
||||||
|
{
|
||||||
|
return *this == other || *this < other;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bitwise
|
||||||
|
template<Unsigned T>
|
||||||
|
ALWAYS_INLINE constexpr T operator&(const T& other) const
|
||||||
|
{
|
||||||
|
return m_low & other;
|
||||||
|
}
|
||||||
|
template<Unsigned T>
|
||||||
|
ALWAYS_INLINE constexpr u128 operator|(const T& other) const
|
||||||
|
{
|
||||||
|
return { m_low | other, m_high };
|
||||||
|
}
|
||||||
|
template<Unsigned T>
|
||||||
|
ALWAYS_INLINE constexpr u128 operator^(const T& other) const
|
||||||
|
{
|
||||||
|
return { m_low ^ other, m_high };
|
||||||
|
}
|
||||||
|
template<Unsigned T>
|
||||||
|
ALWAYS_INLINE constexpr u128 operator<<(const T& other) const
|
||||||
|
{
|
||||||
|
u64 overflow = m_low >> (64 - other);
|
||||||
|
return { m_low << other, (m_high << other) | overflow };
|
||||||
|
}
|
||||||
|
template<Unsigned T>
|
||||||
|
ALWAYS_INLINE constexpr u128 operator>>(const T& other) const
|
||||||
|
{
|
||||||
|
u64 underflow = m_high & other;
|
||||||
|
return { (m_low >> other) | (underflow << (64 - other)), m_high >> other };
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE constexpr u128 operator&(const u128& other) const
|
||||||
|
{
|
||||||
|
return { m_low & other.low(), m_high & other.high() };
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr u128 operator|(const u128& other) const
|
||||||
|
{
|
||||||
|
return { m_low | other.low(), m_high | other.high() };
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr u128 operator^(const u128& other) const
|
||||||
|
{
|
||||||
|
return { m_low ^ other.low(), m_high ^ other.high() };
|
||||||
|
}
|
||||||
|
|
||||||
|
// bitwise assign
|
||||||
|
template<Unsigned T>
|
||||||
|
constexpr u128& operator&=(const T& other)
|
||||||
|
{
|
||||||
|
m_high = 0;
|
||||||
|
m_low &= other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<Unsigned T>
|
||||||
|
constexpr u128& operator|=(const T& other)
|
||||||
|
{
|
||||||
|
m_low |= other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<Unsigned T>
|
||||||
|
constexpr u128& operator^=(const T& other)
|
||||||
|
{
|
||||||
|
m_low ^= other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<Unsigned T>
|
||||||
|
constexpr u128& operator>>=(const T& other)
|
||||||
|
{
|
||||||
|
*this = *this >> other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<Unsigned T>
|
||||||
|
constexpr u128& operator<<=(const T& other)
|
||||||
|
{
|
||||||
|
*this = *this << other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr u128& operator&=(const u128& other)
|
||||||
|
{
|
||||||
|
m_high &= other.high();
|
||||||
|
m_low &= other.low();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
constexpr u128& operator|=(const u128& other)
|
||||||
|
{
|
||||||
|
m_high |= other.high();
|
||||||
|
m_low |= other.low();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
constexpr u128& operator^=(const u128& other)
|
||||||
|
{
|
||||||
|
m_high ^= other.high();
|
||||||
|
m_low ^= other.low();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
union {
|
||||||
|
u8 m_bytes[16] = { 0 };
|
||||||
|
struct {
|
||||||
|
u64 m_low;
|
||||||
|
u64 m_high;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(u128) == 16);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Unsigned_128 = IsUnsigned<T> || IsSame<T, u128>;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
using X86::u128;
|
||||||
|
using X86::Unsigned_128;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct AK::Formatter<u128> : StandardFormatter {
|
||||||
|
Formatter() = default;
|
||||||
|
explicit Formatter(StandardFormatter formatter)
|
||||||
|
: StandardFormatter(formatter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void format(AK::FormatBuilder&, u128);
|
||||||
|
};
|
268
Userland/Libraries/LibX86/Types/u256.h
Normal file
268
Userland/Libraries/LibX86/Types/u256.h
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Leon Albrecht <leon2002.la@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "u128.h"
|
||||||
|
|
||||||
|
#include <AK/Concepts.h>
|
||||||
|
#include <AK/Format.h>
|
||||||
|
#include <AK/Types.h>
|
||||||
|
|
||||||
|
namespace X86 {
|
||||||
|
|
||||||
|
class u256 {
|
||||||
|
public:
|
||||||
|
constexpr u256() = default;
|
||||||
|
constexpr u256(u64 val)
|
||||||
|
: m_low(val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
constexpr u256(u128 val)
|
||||||
|
: m_low(val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
constexpr u256(u128 val_low, u128 val_high)
|
||||||
|
: m_low(val_low)
|
||||||
|
, m_high(val_high)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE u8* bytes()
|
||||||
|
{
|
||||||
|
return (u8*)this;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE const u8* bytes() const
|
||||||
|
{
|
||||||
|
return (const u8*)this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE u16* words()
|
||||||
|
{
|
||||||
|
return (u16*)this;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE const u16* words() const
|
||||||
|
{
|
||||||
|
return (const u16*)this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE u32* double_words()
|
||||||
|
{
|
||||||
|
return (u32*)this;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE const u32* double_words() const
|
||||||
|
{
|
||||||
|
return (const u32*)this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE constexpr u128& low()
|
||||||
|
{
|
||||||
|
return m_low;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr const u128& low() const
|
||||||
|
{
|
||||||
|
return m_low;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE constexpr u128& high()
|
||||||
|
{
|
||||||
|
return m_high;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr const u128& high() const
|
||||||
|
{
|
||||||
|
return m_high;
|
||||||
|
}
|
||||||
|
// conversion
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
ALWAYS_INLINE constexpr operator T() const
|
||||||
|
{
|
||||||
|
return m_low;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE constexpr operator bool() const
|
||||||
|
{
|
||||||
|
return m_low || m_high;
|
||||||
|
}
|
||||||
|
|
||||||
|
// comparisons
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
ALWAYS_INLINE constexpr bool operator==(const T& other) const
|
||||||
|
{
|
||||||
|
return !m_high && m_low == other;
|
||||||
|
}
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
ALWAYS_INLINE constexpr bool operator!=(const T& other) const
|
||||||
|
{
|
||||||
|
return m_high || m_low != other;
|
||||||
|
}
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
ALWAYS_INLINE constexpr bool operator>(const T& other) const
|
||||||
|
{
|
||||||
|
return m_high || m_low > other;
|
||||||
|
}
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
ALWAYS_INLINE constexpr bool operator<(const T& other) const
|
||||||
|
{
|
||||||
|
return !m_high && m_low < other;
|
||||||
|
}
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
ALWAYS_INLINE constexpr bool operator>=(const T& other) const
|
||||||
|
{
|
||||||
|
return *this == other || *this > other;
|
||||||
|
}
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
ALWAYS_INLINE constexpr bool operator<=(const T& other) const
|
||||||
|
{
|
||||||
|
return *this == other || *this < other;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE constexpr bool operator==(const u256& other) const
|
||||||
|
{
|
||||||
|
return m_low == other.low() && m_high == other.high();
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr bool operator!=(const u256& other) const
|
||||||
|
{
|
||||||
|
return m_low != other.low() || m_high != other.high();
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr bool operator>(const u256& other) const
|
||||||
|
{
|
||||||
|
return m_high > other.high()
|
||||||
|
|| (m_high == other.high() && m_low > other.low());
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr bool operator<(const u256& other) const
|
||||||
|
{
|
||||||
|
return m_high < other.high()
|
||||||
|
|| (m_high == other.high() && m_low < other.low());
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr bool operator>=(const u256& other) const
|
||||||
|
{
|
||||||
|
return *this == other || *this > other;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr bool operator<=(const u256& other) const
|
||||||
|
{
|
||||||
|
return *this == other || *this < other;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bitwise
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
ALWAYS_INLINE constexpr T operator&(const T& other) const
|
||||||
|
{
|
||||||
|
return m_low & other;
|
||||||
|
}
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
ALWAYS_INLINE constexpr u256 operator|(const T& other) const
|
||||||
|
{
|
||||||
|
return { m_low | other, m_high };
|
||||||
|
}
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
ALWAYS_INLINE constexpr u256 operator^(const T& other) const
|
||||||
|
{
|
||||||
|
return { m_low ^ other, m_high };
|
||||||
|
}
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
ALWAYS_INLINE constexpr u256 operator<<(const T& other) const
|
||||||
|
{
|
||||||
|
u128 overflow = m_low >> (128 - other);
|
||||||
|
return { m_low << other, (m_high << other) | overflow };
|
||||||
|
}
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
ALWAYS_INLINE constexpr u256 operator>>(const T& other) const
|
||||||
|
{
|
||||||
|
u128 underflow = m_high & other;
|
||||||
|
return { (m_low >> other) | (underflow << (128 - other)), m_high >> other };
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE constexpr u256 operator&(const u256& other) const
|
||||||
|
{
|
||||||
|
return { m_low & other.low(), m_high & other.high() };
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr u256 operator|(const u256& other) const
|
||||||
|
{
|
||||||
|
return { m_low | other.low(), m_high | other.high() };
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE constexpr u256 operator^(const u256& other) const
|
||||||
|
{
|
||||||
|
return { m_low ^ other.low(), m_high ^ other.high() };
|
||||||
|
}
|
||||||
|
|
||||||
|
// bitwise assign
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
constexpr u256& operator&=(const T& other)
|
||||||
|
{
|
||||||
|
m_high = 0;
|
||||||
|
m_low &= other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
constexpr u256& operator|=(const T& other)
|
||||||
|
{
|
||||||
|
m_low |= other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
constexpr u256& operator^=(const T& other)
|
||||||
|
{
|
||||||
|
m_low ^= other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
constexpr u256& operator>>=(const T& other)
|
||||||
|
{
|
||||||
|
*this = *this >> other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<Unsigned_128 T>
|
||||||
|
constexpr u256& operator<<=(const T& other)
|
||||||
|
{
|
||||||
|
*this = *this << other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr u256& operator&=(const u256& other)
|
||||||
|
{
|
||||||
|
m_high &= other.high();
|
||||||
|
m_low &= other.low();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
constexpr u256& operator|=(const u256& other)
|
||||||
|
{
|
||||||
|
m_high |= other.high();
|
||||||
|
m_low |= other.low();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
constexpr u256& operator^=(const u256& other)
|
||||||
|
{
|
||||||
|
m_high ^= other.high();
|
||||||
|
m_low ^= other.low();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// FIXME: Somehow make this a union to directly expose the bytes (see u128)
|
||||||
|
u128 m_low {};
|
||||||
|
u128 m_high {};
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(u256) == 32);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Unsigned_256 = IsUnsigned<T> || IsSame<T, u128> || IsSame<T, u256>;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
using X86::u256;
|
||||||
|
using X86::Unsigned_256;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct AK::Formatter<u256> : StandardFormatter {
|
||||||
|
Formatter() = default;
|
||||||
|
explicit Formatter(StandardFormatter formatter)
|
||||||
|
: StandardFormatter(formatter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void format(AK::FormatBuilder&, u256);
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue