mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 16:57:46 +00:00
AK+LibX86: Generalize u128/256 to AK::UFixedBigInt
Doing these as custom classes might be faster, especially when writing them in SSE, but this would cause a lot of Code duplication and due to the nature of constexprs and the intelligence of the compiler they might be using SSE/MMX either way
This commit is contained in:
parent
9270fb1e69
commit
5ffe23e4f3
11 changed files with 905 additions and 665 deletions
|
@ -1,6 +1,5 @@
|
|||
set(SOURCES
|
||||
Instruction.cpp
|
||||
Types/Formatter.cpp
|
||||
)
|
||||
|
||||
serenity_lib(LibX86 x86)
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/*
|
||||
* 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"
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
|
@ -1,268 +0,0 @@
|
|||
/*
|
||||
* 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);
|
||||
};
|
|
@ -1,268 +0,0 @@
|
|||
/*
|
||||
* 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