#pragma once #include "YBaseLib/Common.h" #include #include #include // Force inline helper #ifndef ALWAYS_INLINE #if defined(_MSC_VER) #define ALWAYS_INLINE __forceinline #elif defined(__GNUC__) || defined(__clang__) #define ALWAYS_INLINE __attribute__((always_inline)) inline #else #define ALWAYS_INLINE inline #endif #endif using s8 = int8_t; using u8 = uint8_t; using s16 = int16_t; using u16 = uint16_t; using s32 = int32_t; using u32 = uint32_t; using s64 = int64_t; using u64 = uint64_t; // Enable use of static_assert in constexpr if template struct dependent_false : std::false_type { }; template struct dependent_int_false : std::false_type { }; // Use a signed number for cycle counting using CycleCount = int64_t; // Use int64 for time tracking using SimulationTime = int64_t; // Helpers for simulation time. ALWAYS_INLINE constexpr SimulationTime SecondsToSimulationTime(SimulationTime s) { return s * INT64_C(1000000000); } ALWAYS_INLINE constexpr SimulationTime MillisecondsToSimulationTime(SimulationTime ms) { return ms * INT64_C(1000000); } ALWAYS_INLINE constexpr SimulationTime MicrosecondsToSimulationTime(SimulationTime us) { return us * INT64_C(1000); } ALWAYS_INLINE constexpr SimulationTime SimulationTimeToSeconds(SimulationTime s) { return s / INT64_C(1000000000); } ALWAYS_INLINE constexpr SimulationTime SimulationTimeToMilliseconds(SimulationTime ms) { return ms / INT64_C(1000000); } ALWAYS_INLINE constexpr SimulationTime SimulationTimeToMicroseconds(SimulationTime us) { return us / INT64_C(1000); } // Calculates the difference between the specified timestamps, accounting for signed overflow. ALWAYS_INLINE constexpr SimulationTime GetSimulationTimeDifference(SimulationTime prev, SimulationTime now) { if (prev <= now) return now - prev; else return (std::numeric_limits::max() - prev) + now; } // Zero-extending helper template ALWAYS_INLINE constexpr TReturn ZeroExtend(TValue value) { return static_cast(static_cast::type>( static_cast::type>(value))); } // Sign-extending helper template ALWAYS_INLINE constexpr TReturn SignExtend(TValue value) { return static_cast( static_cast::type>(static_cast::type>(value))); } // Type-specific helpers template ALWAYS_INLINE constexpr u16 ZeroExtend16(TValue value) { return ZeroExtend(value); } template ALWAYS_INLINE constexpr u32 ZeroExtend32(TValue value) { return ZeroExtend(value); } template ALWAYS_INLINE constexpr u64 ZeroExtend64(TValue value) { return ZeroExtend(value); } template ALWAYS_INLINE constexpr u16 SignExtend16(TValue value) { return SignExtend(value); } template ALWAYS_INLINE constexpr u32 SignExtend32(TValue value) { return SignExtend(value); } template ALWAYS_INLINE constexpr u64 SignExtend64(TValue value) { return SignExtend(value); } template ALWAYS_INLINE constexpr u8 Truncate8(TValue value) { return static_cast(static_cast::type>(value)); } template ALWAYS_INLINE constexpr u16 Truncate16(TValue value) { return static_cast(static_cast::type>(value)); } template ALWAYS_INLINE constexpr u32 Truncate32(TValue value) { return static_cast(static_cast::type>(value)); } // BCD helpers ALWAYS_INLINE constexpr u8 BinaryToBCD(u8 value) { return ((value / 10) << 4) + (value % 10); } ALWAYS_INLINE constexpr u8 PackedBCDToBinary(u8 value) { return ((value >> 4) * 10) + (value % 16); } ALWAYS_INLINE constexpr u8 IsValidBCDDigit(u8 digit) { return (digit <= 9); } ALWAYS_INLINE constexpr u8 IsValidPackedBCD(u8 value) { return IsValidBCDDigit(value & 0x0F) && IsValidBCDDigit(value >> 4); } // Boolean to integer ALWAYS_INLINE constexpr u8 BoolToUInt8(bool value) { return static_cast(value); } ALWAYS_INLINE constexpr u16 BoolToUInt16(bool value) { return static_cast(value); } ALWAYS_INLINE constexpr u32 BoolToUInt32(bool value) { return static_cast(value); } ALWAYS_INLINE constexpr u64 BoolToUInt64(bool value) { return static_cast(value); } // Integer to boolean template ALWAYS_INLINE constexpr bool ConvertToBool(TValue value) { return static_cast(value); } // Unsafe integer to boolean template ALWAYS_INLINE bool ConvertToBoolUnchecked(TValue value) { // static_assert(sizeof(uint8) == sizeof(bool)); bool ret; std::memcpy(&ret, &value, sizeof(bool)); return ret; } // Generic sign extension template ALWAYS_INLINE constexpr T SignExtendN(T value) { // http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend constexpr int shift = 8 * sizeof(T) - NBITS; return static_cast((static_cast>(value) << shift) >> shift); } // Enum class bitwise operators #define IMPLEMENT_ENUM_CLASS_BITWISE_OPERATORS(type_) \ ALWAYS_INLINE constexpr type_ operator&(type_ lhs, type_ rhs) \ { \ return static_cast(static_cast::type>(lhs) & \ static_cast::type>(rhs)); \ } \ ALWAYS_INLINE constexpr type_ operator|(type_ lhs, type_ rhs) \ { \ return static_cast(static_cast::type>(lhs) | \ static_cast::type>(rhs)); \ } \ ALWAYS_INLINE constexpr type_ operator^(type_ lhs, type_ rhs) \ { \ return static_cast(static_cast::type>(lhs) ^ \ static_cast::type>(rhs)); \ } \ ALWAYS_INLINE constexpr type_ operator~(type_ val) \ { \ return static_cast(~static_cast::type>(val)); \ } \ ALWAYS_INLINE constexpr type_& operator&=(type_& lhs, type_ rhs) \ { \ lhs = static_cast(static_cast::type>(lhs) & \ static_cast::type>(rhs)); \ return lhs; \ } \ ALWAYS_INLINE constexpr type_& operator|=(type_& lhs, type_ rhs) \ { \ lhs = static_cast(static_cast::type>(lhs) | \ static_cast::type>(rhs)); \ return lhs; \ } \ ALWAYS_INLINE constexpr type_& operator^=(type_& lhs, type_ rhs) \ { \ lhs = static_cast(static_cast::type>(lhs) ^ \ static_cast::type>(rhs)); \ return lhs; \ }