BEType: explicit alignment specifier

This commit is contained in:
Nekotekina 2016-05-26 18:06:06 +03:00
parent 5d6aecc599
commit 73c2115968
7 changed files with 177 additions and 125 deletions

View file

@ -327,14 +327,44 @@ inline v128 operator ~(const v128& other)
#define IS_INTEGER(t) (std::is_integral<t>::value || std::is_enum<t>::value)
#define IS_BINARY_COMPARABLE(t1, t2) (IS_INTEGER(t1) && IS_INTEGER(t2) && sizeof(t1) == sizeof(t2))
template<typename T, std::size_t Size = sizeof(T)>
template<typename T, std::size_t Align, std::size_t Size>
struct se_storage
{
static_assert(!Size, "Bad se_storage<> type");
using type = std::aligned_storage_t<Size, Align>;
// Unoptimized generic byteswap for unaligned data
static void reverse(u8* dst, const u8* src)
{
for (std::size_t i = 0; i < Size; i++)
{
dst[i] = src[Size - 1 - i];
}
}
static type to(const T& src)
{
type result;
reverse(reinterpret_cast<u8*>(&result), reinterpret_cast<const u8*>(&src));
return result;
}
static T from(const type& src)
{
T result;
reverse(reinterpret_cast<u8*>(&result), reinterpret_cast<const u8*>(&src));
return result;
}
static type copy(const type& src)
{
type result;
std::memcpy(&result, &src, Size);
return result;
}
};
template<typename T>
struct se_storage<T, 2>
struct se_storage<T, 2, 2>
{
using type = u16;
@ -357,10 +387,15 @@ struct se_storage<T, 2>
const u16 result = swap(src);
return reinterpret_cast<const T&>(result);
}
static inline T copy(const T& src)
{
return src;
}
};
template<typename T>
struct se_storage<T, 4>
struct se_storage<T, 4, 4>
{
using type = u32;
@ -383,10 +418,15 @@ struct se_storage<T, 4>
const u32 result = swap(src);
return reinterpret_cast<const T&>(result);
}
static inline T copy(const T& src)
{
return src;
}
};
template<typename T>
struct se_storage<T, 8>
struct se_storage<T, 8, 8>
{
using type = u64;
@ -409,10 +449,15 @@ struct se_storage<T, 8>
const u64 result = swap(src);
return reinterpret_cast<const T&>(result);
}
static inline T copy(const T& src)
{
return src;
}
};
template<typename T>
struct se_storage<T, 16>
struct se_storage<T, 16, 16>
{
using type = v128;
@ -431,43 +476,22 @@ struct se_storage<T, 16>
const v128 result = swap(src);
return reinterpret_cast<const T&>(result);
}
};
template<typename T> using se_storage_t = typename se_storage<T>::type;
template<typename T1, typename T2>
struct se_convert
{
using type_from = std::remove_cv_t<T1>;
using type_to = std::remove_cv_t<T2>;
using stype_from = se_storage_t<std::remove_cv_t<T1>>;
using stype_to = se_storage_t<std::remove_cv_t<T2>>;
using storage_from = se_storage<std::remove_cv_t<T1>>;
using storage_to = se_storage<std::remove_cv_t<T2>>;
static inline std::enable_if_t<std::is_same<type_from, type_to>::value, stype_to> convert(const stype_from& data)
static inline T copy(const T& src)
{
return data;
}
static inline stype_to convert(const stype_from& data, ...)
{
return storage_to::to(storage_from::from(data));
return src;
}
};
static struct se_raw_tag_t {} constexpr se_raw{};
template<typename T, bool Se = true>
class se_t;
// Switched endianness
template<typename T>
class se_t<T, true>
template<typename T, std::size_t Align>
class se_t<T, true, Align>
{
using type = typename std::remove_cv<T>::type;
using stype = se_storage_t<type>;
using storage = se_storage<type>;
using stype = typename se_storage<type, Align>::type;
using storage = se_storage<type, Align>;
stype m_data;
@ -585,39 +609,41 @@ public:
};
// Native endianness
template<typename T>
class se_t<T, false>
template<typename T, std::size_t Align>
class se_t<T, false, Align>
{
using type = typename std::remove_cv<T>::type;
using stype = typename se_storage<type, Align>::type;
using storage = se_storage<type, Align>;
static_assert(!std::is_pointer<type>::value, "se_t<> error: invalid type (pointer)");
static_assert(!std::is_reference<type>::value, "se_t<> error: invalid type (reference)");
static_assert(!std::is_array<type>::value, "se_t<> error: invalid type (array)");
static_assert(sizeof(type) == alignof(type), "se_t<> error: unexpected alignment");
type m_data;
stype m_data;
public:
se_t() = default;
constexpr se_t(type value)
: m_data(value)
se_t(type value)
: m_data(reinterpret_cast<const stype&>(value))
{
}
// Construct directly from raw data (don't use)
constexpr se_t(const type& raw_value, const se_raw_tag_t&)
constexpr se_t(const stype& raw_value, const se_raw_tag_t&)
: m_data(raw_value)
{
}
constexpr type value() const
type value() const
{
return m_data;
return storage::copy(reinterpret_cast<const type&>(m_data));
}
// Access underlying raw data (don't use)
constexpr const type& raw_data() const noexcept
constexpr const stype& raw_data() const noexcept
{
return m_data;
}
@ -626,14 +652,14 @@ public:
se_t& operator =(type value)
{
return m_data = value, *this;
return m_data = reinterpret_cast<const stype&>(value), *this;
}
using simple_type = simple_t<T>;
constexpr operator type() const
operator type() const
{
return m_data;
return storage::copy(reinterpret_cast<const type&>(m_data));
}
template<typename CT>
@ -656,59 +682,59 @@ public:
};
// se_t with native endianness (alias)
template<typename T> using nse_t = se_t<T, false>;
template<typename T, std::size_t Align = alignof(T)> using nse_t = se_t<T, false, Align>;
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator +=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator +=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value += right);
}
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator -=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator -=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value -= right);
}
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator *=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator *=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value *= right);
}
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator /=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator /=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value /= right);
}
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator %=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator %=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value %= right);
}
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator <<=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator <<=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value <<= right);
}
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator >>=(se_t<T, Se>& left, const T1& right)
template<typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator >>=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value >>= right);
}
template<typename T, bool Se>
inline se_t<T, Se> operator ++(se_t<T, Se>& left, int)
template<typename T, bool Se, std::size_t Align>
inline se_t<T, Se, Align> operator ++(se_t<T, Se, Align>& left, int)
{
auto value = left.value();
auto result = value++;
@ -716,8 +742,8 @@ inline se_t<T, Se> operator ++(se_t<T, Se>& left, int)
return result;
}
template<typename T, bool Se>
inline se_t<T, Se> operator --(se_t<T, Se>& left, int)
template<typename T, bool Se, std::size_t Align>
inline se_t<T, Se, Align> operator --(se_t<T, Se, Align>& left, int)
{
auto value = left.value();
auto result = value--;
@ -725,15 +751,15 @@ inline se_t<T, Se> operator --(se_t<T, Se>& left, int)
return result;
}
template<typename T, bool Se>
inline se_t<T, Se>& operator ++(se_t<T, Se>& right)
template<typename T, bool Se, std::size_t Align>
inline se_t<T, Se, Align>& operator ++(se_t<T, Se, Align>& right)
{
auto value = right.value();
return right = ++value;
}
template<typename T, bool Se>
inline se_t<T, Se>& operator --(se_t<T, Se>& right)
template<typename T, bool Se, std::size_t Align>
inline se_t<T, Se, Align>& operator --(se_t<T, Se, Align>& right)
{
auto value = right.value();
return right = --value;
@ -852,16 +878,28 @@ inline std::enable_if_t<std::is_integral<T>::value && sizeof(T) >= 4, se_t<declt
}
#if IS_LE_MACHINE == 1
template<typename T> using be_t = se_t<T, true>;
template<typename T> using le_t = se_t<T, false>;
template<typename T, std::size_t Align = alignof(T)> using be_t = se_t<T, true, Align>;
template<typename T, std::size_t Align = alignof(T)> using le_t = se_t<T, false, Align>;
#endif
// Type converter: converts native endianness arithmetic/enum types to appropriate se_t<> type
template<typename T, bool Se, typename = void>
struct to_se
{
template<typename T2, typename = void>
struct to_se_
{
using type = T2;
};
template<typename T2>
struct to_se_<T2, std::enable_if_t<std::is_arithmetic<T2>::value || std::is_enum<T2>::value>>
{
using type = se_t<T2, Se>;
};
// Convert arithmetic and enum types
using type = typename std::conditional<std::is_arithmetic<T>::value || std::is_enum<T>::value, se_t<T, Se>, T>::type;
using type = typename to_se_<T>::type;
};
template<bool Se> struct to_se<v128, Se> { using type = se_t<v128, Se>; };
@ -911,10 +949,10 @@ template<typename T> using atomic_le_t = atomic_t<le_t<T>>;
#endif
// Formatting for BE/LE data
template<typename T, bool Se>
struct unveil<se_t<T, Se>, void>
template<typename T, bool Se, std::size_t Align>
struct unveil<se_t<T, Se, Align>, void>
{
static inline auto get(const se_t<T, Se>& arg)
static inline auto get(const se_t<T, Se, Align>& arg)
{
return unveil<T>::get(arg);
}

View file

@ -34,6 +34,12 @@ struct bijective_pair
T2 v2;
};
template<typename T, std::size_t Align = alignof(T), std::size_t Size = sizeof(T)>
struct se_storage;
template<typename T, bool Se = true, std::size_t Align = alignof(T)>
class se_t;
// Specialization with static constexpr bijective_pair<T1, T2> map[] member expected
template<typename T1, typename T2>
struct bijective;

View file

@ -253,8 +253,6 @@ struct CellPamfLpcmInfo
#pragma pack(push, 1) // file data
struct PamfStreamHeader
{
u8 type;
@ -341,7 +339,7 @@ struct PamfStreamHeader
};
};
CHECK_SIZE(PamfStreamHeader, 48);
CHECK_SIZE_ALIGN(PamfStreamHeader, 48, 4);
struct PamfHeader
{
@ -349,25 +347,25 @@ struct PamfHeader
u32 version; //"0041" (is it const?)
be_t<u32> data_offset; //== 2048 >> 11, PAMF headers seem to be always 2048 bytes in size
be_t<u32> data_size; //== ((fileSize - 2048) >> 11)
u64 reserved[8];
u32 reserved[16];
be_t<u32> table_size; //== size of mapping-table
u16 reserved1;
be_t<u16> start_pts_high;
be_t<u32> start_pts_low; //Presentation Time Stamp (start)
be_t<u32, 2> start_pts_low; //Presentation Time Stamp (start)
be_t<u16> end_pts_high;
be_t<u32> end_pts_low; //Presentation Time Stamp (end)
be_t<u32> mux_rate_max; //== 0x01D470 (400 bps per unit, == 48000000 bps)
be_t<u32> mux_rate_min; //== 0x0107AC (?????)
be_t<u32, 2> end_pts_low; //Presentation Time Stamp (end)
be_t<u32, 2> mux_rate_max; //== 0x01D470 (400 bps per unit, == 48000000 bps)
be_t<u32, 2> mux_rate_min; //== 0x0107AC (?????)
u16 reserved2; // ?????
u8 reserved3;
u8 stream_count; //total stream count (reduced to 1 byte)
be_t<u16> unk1; //== 1 (?????)
be_t<u32> table_data_size; //== table_size - 0x20 == 0x14 + (0x30 * total_stream_num) (?????)
be_t<u32, 2> table_data_size; //== table_size - 0x20 == 0x14 + (0x30 * total_stream_num) (?????)
//TODO: check relative offset of stream structs (could be from 0x0c to 0x14, currently 0x14)
be_t<u16> start_pts_high2; //????? (probably same values)
be_t<u32> start_pts_low2; //?????
be_t<u32, 2> start_pts_low2; //?????
be_t<u16> end_pts_high2; //?????
be_t<u32> end_pts_low2; //?????
be_t<u32, 2> end_pts_low2; //?????
be_t<u32> unk2; //== 0x10000 (?????)
be_t<u16> unk3; // ?????
be_t<u16> unk4; // == stream_count
@ -375,6 +373,8 @@ struct PamfHeader
PamfStreamHeader stream_headers[256];
};
CHECK_SIZE_ALIGN(PamfHeader, 136 + sizeof(PamfHeader::stream_headers), 4);
struct PamfEpHeader
{
be_t<u16> value0; //mixed indexN (probably left 2 bits) and nThRefPictureOffset
@ -383,9 +383,7 @@ struct PamfEpHeader
be_t<u32> rpnOffset;
};
CHECK_SIZE(PamfEpHeader, 12);
#pragma pack(pop)
CHECK_SIZE_ALIGN(PamfEpHeader, 12, 4);
// not directly accessed by virtual CPU, fields are unknown
struct CellPamfReader

View file

@ -7,8 +7,6 @@
namespace vm { using namespace ps3; }
#pragma pack(push, 4)
// Error Codes
enum : s32
{
@ -136,20 +134,22 @@ struct CellFsStat
be_t<s32> mode;
be_t<s32> uid;
be_t<s32> gid;
be_t<s64> atime;
be_t<s64> mtime;
be_t<s64> ctime;
be_t<u64> size;
be_t<u64> blksize;
be_t<s64, 4> atime;
be_t<s64, 4> mtime;
be_t<s64, 4> ctime;
be_t<u64, 4> size;
be_t<u64, 4> blksize;
};
CHECK_SIZE_ALIGN(CellFsStat, 52, 4);
struct CellFsUtimbuf
{
be_t<s64> actime;
be_t<s64> modtime;
be_t<s64, 4> actime;
be_t<s64, 4> modtime;
};
#pragma pack(pop)
CHECK_SIZE_ALIGN(CellFsUtimbuf, 16, 4);
// Stream Support Status (st_status)
enum : u32

View file

@ -130,6 +130,18 @@ namespace vm
return aligned(ALIGN_32(T));
}
// Get type size
static constexpr u32 size()
{
return SIZE_32(T);
}
// Get type alignment
static constexpr u32 align()
{
return ALIGN_32(T);
}
// Test address for arbitrary alignment: (addr & (align - 1)) != 0
explicit_bool_t operator %(u32 align) const
{
@ -266,9 +278,11 @@ namespace vm
// Native endianness pointer to LE data
template<typename T, typename AT = u32> using ptrl = _ptr_base<to_le_t<T>, AT>;
template<typename T, typename AT = u32> using cptrl = ptrl<const T, AT>;
// Native endianness pointer to BE data
template<typename T, typename AT = u32> using ptrb = _ptr_base<to_be_t<T>, AT>;
template<typename T, typename AT = u32> using cptrb = ptrb<const T, AT>;
// BE pointer to LE data
template<typename T, typename AT = u32> using bptrl = _ptr_base<to_le_t<T>, to_be_t<AT>>;
@ -286,24 +300,19 @@ namespace vm
{
// Default pointer type for PS3 HLE functions (Native endianness pointer to BE data)
template<typename T, typename AT = u32> using ptr = ptrb<T, AT>;
template<typename T, typename AT = u32> using cptr = ptr<const T, AT>;
// Default pointer to pointer type for PS3 HLE functions (Native endianness pointer to BE pointer to BE data)
template<typename T, typename AT = u32, typename AT2 = u32> using pptr = ptr<ptr<T, AT2>, AT>;
template<typename T, typename AT = u32, typename AT2 = u32> using cpptr = pptr<const T, AT, AT2>;
// Default pointer type for PS3 HLE structures (BE pointer to BE data)
template<typename T, typename AT = u32> using bptr = bptrb<T, AT>;
template<typename T, typename AT = u32> using bcptr = bptr<const T, AT>;
// Default pointer to pointer type for PS3 HLE structures (BE pointer to BE pointer to BE data)
template<typename T, typename AT = u32, typename AT2 = u32> using bpptr = bptr<ptr<T, AT2>, AT>;
// Native endianness pointer to const BE data
template<typename T, typename AT = u32> using cptr = ptr<const T, AT>;
// BE pointer to const BE data
template<typename T, typename AT = u32> using bcptr = bptr<const T, AT>;
template<typename T, typename AT = u32> using cpptr = pptr<const T, AT>;
template<typename T, typename AT = u32> using bcpptr = bpptr<const T, AT>;
template<typename T, typename AT = u32, typename AT2 = u32> using bcpptr = bpptr<const T, AT, AT2>;
// Perform static_cast (for example, vm::ptr<void> to vm::ptr<char>)
template<typename CT, typename T, typename AT, typename = decltype(static_cast<to_be_t<CT>*>(std::declval<T*>()))>
@ -324,23 +333,18 @@ namespace vm
{
// Default pointer type for PSV HLE functions (Native endianness pointer to LE data)
template<typename T> using ptr = ptrl<T>;
template<typename T> using cptr = ptr<const T>;
// Default pointer to pointer type for PSV HLE functions (Native endianness pointer to LE pointer to LE data)
template<typename T> using pptr = ptr<ptr<T>>;
template<typename T> using cpptr = pptr<const T>;
// Default pointer type for PSV HLE structures (LE pointer to LE data)
template<typename T> using lptr = lptrl<T>;
template<typename T> using lcptr = lptr<const T>;
// Default pointer to pointer type for PSV HLE structures (LE pointer to LE pointer to LE data)
template<typename T> using lpptr = lptr<ptr<T>>;
// Native endianness pointer to const LE data
template<typename T> using cptr = ptr<const T>;
// LE pointer to const LE data
template<typename T> using lcptr = lptr<const T>;
template<typename T> using cpptr = pptr<const T>;
template<typename T> using lcpptr = lpptr<const T>;
// Perform static_cast (for example, vm::ptr<void> to vm::ptr<char>)

View file

@ -109,10 +109,10 @@ namespace vm
template<typename T, typename A = stack_allocator> using var = varb<T, A>;
// Make BE variable initialized from value
template<typename T> inline auto make_var(const T& value)
template<typename T>
inline auto make_var(const T& value)
{
varb<T, stack_allocator> var(value);
return var;
return varb<T>(value);
}
// Global HLE variable
@ -128,10 +128,10 @@ namespace vm
template<typename T, typename A = stack_allocator> using var = varl<T, A>;
// Make LE variable initialized from value
template<typename T> inline auto make_var(const T& value)
template<typename T>
inline auto make_var(const T& value)
{
varl<T, stack_allocator> var(value);
return var;
return varl<T>(value);
}
// Global HLE variable

View file

@ -32,6 +32,12 @@ enum class elf_machine : u16
mips = 0x08,
};
template<typename T>
using elf_be = be_t<T>;
template<typename T>
using elf_le = le_t<T>;
template<template<typename T> class en_t, typename sz_t>
struct elf_ehdr
{
@ -341,7 +347,7 @@ public:
}
};
using ppu_exec_object = elf_object<be_t, u64, elf_machine::ppc64, elf_os::none, elf_type::exec>;
using ppu_prx_object = elf_object<be_t, u64, elf_machine::ppc64, elf_os::lv2, elf_type::prx>;
using spu_exec_object = elf_object<be_t, u32, elf_machine::spu, elf_os::none, elf_type::exec>;
using arm_exec_object = elf_object<le_t, u32, elf_machine::arm, elf_os::none, elf_type::none>;
using ppu_exec_object = elf_object<elf_be, u64, elf_machine::ppc64, elf_os::none, elf_type::exec>;
using ppu_prx_object = elf_object<elf_be, u64, elf_machine::ppc64, elf_os::lv2, elf_type::prx>;
using spu_exec_object = elf_object<elf_be, u32, elf_machine::spu, elf_os::none, elf_type::exec>;
using arm_exec_object = elf_object<elf_le, u32, elf_machine::arm, elf_os::none, elf_type::none>;