update to 0.9.48

This commit is contained in:
zeromus 2020-04-06 01:58:12 -04:00
parent 79e4e0690b
commit 7cfdc91e1f
7 changed files with 374 additions and 166 deletions

View File

@ -172,3 +172,12 @@
[OK] psx/masmem : not important
[NO] psx/mdec : not important
[NO] psx/psx : not important
0.9.45 -> 0.9.45.1
(nothing)
0.9.45.1 -> 0.9.48
[OK] endian / many updates, probably for performance
[OK] psx/irq : tidy
[OK] psx/gpu : tidy
[OK] tests: add some gcc tests, and tests for various cpu archs

View File

@ -137,3 +137,5 @@ char (*BLAHBLAHBLAH( UNALIGNED T (&)[N] ))[N];
#else
#define EW_PACKED( ... ) __VA_ARGS__ __attribute__((__packed__))
#endif
#define MDFN_IS_BIGENDIAN 0

View File

@ -2,7 +2,7 @@
/* Mednafen - Multi-system Emulator */
/******************************************************************************/
/* endian.h:
** Copyright (C) 2006-2016 Mednafen Team
** Copyright (C) 2006-2017 Mednafen Team
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
@ -82,24 +82,30 @@ static INLINE void BitsIntract(uint8* ptr, const size_t bit_offset, const size_t
static INLINE uint16 MDFN_bswap16(uint16 v)
{
#if defined(_MSC_VER)
return _byteswap_ushort(v);
#else
return (v << 8) | (v >> 8);
#endif
}
static INLINE uint32 MDFN_bswap32(uint32 v)
{
#if defined(_MSC_VER)
return _byteswap_ulong(v);
#else
return (v << 24) | ((v & 0xFF00) << 8) | ((v >> 8) & 0xFF00) | (v >> 24);
#endif
}
static INLINE uint64 MDFN_bswap64(uint64 v)
{
return (v << 56) | (v >> 56) | ((v & 0xFF00) << 40) | ((v >> 40) & 0xFF00) | ((uint64)MDFN_bswap32(v >> 16) << 16);
}
#ifdef LSB_FIRST
#define MDFN_ENDIANH_IS_BIGENDIAN 0
#if defined(_MSC_VER)
return _byteswap_uint64(v);
#else
#define MDFN_ENDIANH_IS_BIGENDIAN 1
return (v << 56) | (v >> 56) | ((v & 0xFF00) << 40) | ((v >> 40) & 0xFF00) | ((uint64)MDFN_bswap32(v >> 16) << 16);
#endif
}
//
// X endian.
@ -109,9 +115,9 @@ static INLINE T MDFN_deXsb(const void* ptr)
{
T tmp;
memcpy(&tmp, MDFN_ASSUME_ALIGNED(ptr, (aligned ? sizeof(T) : 1)), sizeof(T));
memcpy(&tmp, MDFN_ASSUME_ALIGNED(ptr, (aligned ? alignof(T) : 1)), sizeof(T));
if(isbigendian != -1 && isbigendian != MDFN_ENDIANH_IS_BIGENDIAN)
if(isbigendian != -1 && isbigendian != (int)MDFN_IS_BIGENDIAN)
{
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Gummy penguins.");
@ -220,7 +226,7 @@ static INLINE void MDFN_enXsb(void* ptr, T value)
{
T tmp = value;
if(isbigendian != -1 && isbigendian != MDFN_ENDIANH_IS_BIGENDIAN)
if(isbigendian != -1 && isbigendian != (int)MDFN_IS_BIGENDIAN)
{
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Gummy penguins.");
@ -232,7 +238,7 @@ static INLINE void MDFN_enXsb(void* ptr, T value)
tmp = MDFN_bswap16(value);
}
memcpy(MDFN_ASSUME_ALIGNED(ptr, (aligned ? sizeof(T) : 1)), &tmp, sizeof(T));
memcpy(MDFN_ASSUME_ALIGNED(ptr, (aligned ? alignof(T) : 1)), &tmp, sizeof(T));
}
//
@ -325,170 +331,203 @@ static INLINE void MDFN_en64msb(void* ptr, uint64 value)
//
//
template<typename T, typename BT>
static INLINE uint8* ne16_ptr_be(BT* const base, const size_t byte_offset)
template<typename T, typename X>
static INLINE uintptr_t neX_ptr_be(uintptr_t const base, const size_t byte_offset)
{
#ifdef MSB_FIRST
return (uint8*)base + (byte_offset &~ (sizeof(T) - 1));
return base + (byte_offset &~ (sizeof(T) - 1));
#else
return (uint8*)base + (((byte_offset &~ (sizeof(T) - 1)) ^ (2 - std::min<size_t>(2, sizeof(T)))));
return base + (((byte_offset &~ (sizeof(T) - 1)) ^ (sizeof(X) - std::min<size_t>(sizeof(X), sizeof(T)))));
#endif
}
template<typename T>
static INLINE void ne16_wbo_be(uint16* const base, const size_t byte_offset, const T value)
{
uint8* const ptr = ne16_ptr_be<T>(base, byte_offset);
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
if(sizeof(T) == 4)
{
uint16* const ptr16 = (uint16*)ptr;
ptr16[0] = value >> 16;
ptr16[1] = value;
}
else
*(T*)ptr = value;
}
template<typename T>
static INLINE T ne16_rbo_be(const uint16* const base, const size_t byte_offset)
{
uint8* const ptr = ne16_ptr_be<T>(base, byte_offset);
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
if(sizeof(T) == 4)
{
uint16* const ptr16 = (uint16*)ptr;
T tmp;
tmp = ptr16[0] << 16;
tmp |= ptr16[1];
return tmp;
}
else
return *(T*)ptr;
}
template<typename T, bool IsWrite>
static INLINE void ne16_rwbo_be(uint16* const base, const size_t byte_offset, T* value)
{
if(IsWrite)
ne16_wbo_be<T>(base, byte_offset, *value);
else
*value = ne16_rbo_be<T>(base, byte_offset);
}
//
//
//
template<typename T, typename BT>
static INLINE uint8* ne16_ptr_le(BT* const base, const size_t byte_offset)
template<typename T, typename X>
static INLINE uintptr_t neX_ptr_le(uintptr_t const base, const size_t byte_offset)
{
#ifdef LSB_FIRST
return (uint8*)base + (byte_offset &~ (sizeof(T) - 1));
return base + (byte_offset &~ (sizeof(T) - 1));
#else
return (uint8*)base + (((byte_offset &~ (sizeof(T) - 1)) ^ (2 - std::min<size_t>(2, sizeof(T)))));
return base + (((byte_offset &~ (sizeof(T) - 1)) ^ (sizeof(X) - std::min<size_t>(sizeof(X), sizeof(T)))));
#endif
}
template<typename T>
static INLINE void ne16_wbo_le(uint16* const base, const size_t byte_offset, const T value)
template<typename T, typename BT>
static INLINE void ne16_wbo_be(BT base, const size_t byte_offset, const T value)
{
uint8* const ptr = ne16_ptr_le<T>(base, byte_offset);
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
static_assert(std::is_same<BT, uintptr_t>::value || std::is_convertible<BT, uint16*>::value, "Wrong base type");
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
uintptr_t const ptr = neX_ptr_be<T, uint16>((uintptr_t)base, byte_offset);
if(sizeof(T) == 4)
{
uint16* const ptr16 = (uint16*)ptr;
if(sizeof(T) == 4)
{
uint16* const ptr16 = (uint16*)ptr;
ptr16[0] = value;
ptr16[1] = value >> 16;
}
else
*(T*)ptr = value;
ptr16[0] = value >> 16;
ptr16[1] = value;
}
else
*(T*)ptr = value;
}
template<typename T>
static INLINE T ne16_rbo_le(const uint16* const base, const size_t byte_offset)
template<typename T, typename BT>
static INLINE T ne16_rbo_be(BT base, const size_t byte_offset)
{
uint8* const ptr = ne16_ptr_le<T>(base, byte_offset);
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
static_assert(std::is_same<BT, uintptr_t>::value || std::is_convertible<BT, const uint16*>::value, "Wrong base type");
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
uintptr_t const ptr = neX_ptr_be<T, uint16>((uintptr_t)base, byte_offset);
if(sizeof(T) == 4)
{
uint16* const ptr16 = (uint16*)ptr;
T tmp;
if(sizeof(T) == 4)
{
uint16* const ptr16 = (uint16*)ptr;
T tmp;
tmp = ptr16[0];
tmp |= ptr16[1] << 16;
tmp = ptr16[0] << 16;
tmp |= ptr16[1];
return tmp;
}
else
return *(T*)ptr;
return tmp;
}
else
return *(T*)ptr;
}
template<typename T, bool IsWrite>
static INLINE void ne16_rwbo_le(uint16* const base, const size_t byte_offset, T* value)
template<typename T, bool IsWrite, typename BT>
static INLINE void ne16_rwbo_be(BT base, const size_t byte_offset, T* value)
{
if(IsWrite)
ne16_wbo_le<T>(base, byte_offset, *value);
else
*value = ne16_rbo_le<T>(base, byte_offset);
if(IsWrite)
ne16_wbo_be<T>(base, byte_offset, *value);
else
*value = ne16_rbo_be<T>(base, byte_offset);
}
//
//
//
template<typename T>
static INLINE uint8* ne64_ptr_be(uint64* const base, const size_t byte_offset)
template<typename T, typename BT>
static INLINE void ne16_wbo_le(BT base, const size_t byte_offset, const T value)
{
#ifdef MSB_FIRST
return (uint8*)base + (byte_offset &~ (sizeof(T) - 1));
#else
return (uint8*)base + (((byte_offset &~ (sizeof(T) - 1)) ^ (8 - sizeof(T))));
#endif
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
static_assert(std::is_same<BT, uintptr_t>::value || std::is_convertible<BT, uint16*>::value, "Wrong base type");
uintptr_t const ptr = neX_ptr_le<T, uint16>((uintptr_t)base, byte_offset);
if(sizeof(T) == 4)
{
uint16* const ptr16 = (uint16*)ptr;
ptr16[0] = value;
ptr16[1] = value >> 16;
}
else
*(T*)ptr = value;
}
template<typename T>
static INLINE void ne64_wbo_be(uint64* const base, const size_t byte_offset, const T value)
template<typename T, typename BT>
static INLINE T ne16_rbo_le(BT base, const size_t byte_offset)
{
uint8* const ptr = ne64_ptr_be<T>(base, byte_offset);
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
static_assert(std::is_same<BT, uintptr_t>::value || std::is_convertible<BT, const uint16*>::value, "Wrong base type");
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Unsupported type size");
uintptr_t const ptr = neX_ptr_le<T, uint16>((uintptr_t)base, byte_offset);
memcpy(MDFN_ASSUME_ALIGNED(ptr, sizeof(T)), &value, sizeof(T));
if(sizeof(T) == 4)
{
uint16* const ptr16 = (uint16*)ptr;
T tmp;
tmp = ptr16[0];
tmp |= ptr16[1] << 16;
return tmp;
}
else
return *(T*)ptr;
}
template<typename T>
static INLINE T ne64_rbo_be(uint64* const base, const size_t byte_offset)
template<typename T, bool IsWrite, typename BT>
static INLINE void ne16_rwbo_le(BT base, const size_t byte_offset, T* value)
{
uint8* const ptr = ne64_ptr_be<T>(base, byte_offset);
T ret;
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
memcpy(&ret, MDFN_ASSUME_ALIGNED(ptr, sizeof(T)), sizeof(T));
return ret;
if(IsWrite)
ne16_wbo_le<T>(base, byte_offset, *value);
else
*value = ne16_rbo_le<T>(base, byte_offset);
}
template<typename T, bool IsWrite>
static INLINE void ne64_rwbo_be(uint64* const base, const size_t byte_offset, T* value)
//
//
//
template<typename T, typename BT>
static INLINE void ne64_wbo_be(BT base, const size_t byte_offset, const T value)
{
if(IsWrite)
ne64_wbo_be<T>(base, byte_offset, *value);
else
*value = ne64_rbo_be<T>(base, byte_offset);
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Unsupported type size");
static_assert(std::is_same<BT, uintptr_t>::value || std::is_convertible<BT, uint64*>::value, "Wrong base type");
uintptr_t const ptr = neX_ptr_be<T, uint64>((uintptr_t)base, byte_offset);
memcpy(MDFN_ASSUME_ALIGNED((void*)ptr, alignof(T)), &value, sizeof(T));
}
template<typename T, typename BT>
static INLINE T ne64_rbo_be(BT base, const size_t byte_offset)
{
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Unsupported type size");
static_assert(std::is_same<BT, uintptr_t>::value || std::is_convertible<BT, const uint64*>::value, "Wrong base type");
uintptr_t const ptr = neX_ptr_be<T, uint64>((uintptr_t)base, byte_offset);
T ret;
memcpy(&ret, MDFN_ASSUME_ALIGNED((void*)ptr, alignof(T)), sizeof(T));
return ret;
}
template<typename T, bool IsWrite, typename BT>
static INLINE void ne64_rwbo_be(BT base, const size_t byte_offset, T* value)
{
if(IsWrite)
ne64_wbo_be<T>(base, byte_offset, *value);
else
*value = ne64_rbo_be<T>(base, byte_offset);
}
//
//
//
template<typename T, typename BT>
static INLINE void ne64_wbo_le(BT base, const size_t byte_offset, const T value)
{
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Unsupported type size");
static_assert(std::is_same<BT, uintptr_t>::value || std::is_convertible<BT, uint64*>::value, "Wrong base type");
uintptr_t const ptr = neX_ptr_le<T, uint64>((uintptr_t)base, byte_offset);
memcpy(MDFN_ASSUME_ALIGNED((void*)ptr, alignof(T)), &value, sizeof(T));
}
template<typename T, typename BT>
static INLINE T ne64_rbo_le(BT base, const size_t byte_offset)
{
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Unsupported type size");
static_assert(std::is_same<BT, uintptr_t>::value || std::is_convertible<BT, const uint64*>::value, "Wrong base type");
uintptr_t const ptr = neX_ptr_le<T, uint64>((uintptr_t)base, byte_offset);
T ret;
memcpy(&ret, MDFN_ASSUME_ALIGNED((void*)ptr, alignof(T)), sizeof(T));
return ret;
}
template<typename T, bool IsWrite, typename BT>
static INLINE void ne64_rwbo_le(BT base, const size_t byte_offset, T* value)
{
if(IsWrite)
ne64_wbo_le<T>(base, byte_offset, *value);
else
*value = ne64_rbo_le<T>(base, byte_offset);
}
#endif

View File

@ -21,7 +21,7 @@
//
// Reference voodoo, since section anchors don't work with externs
// WARNING: Don't use with members of (transparent) unions!
// WARNING: Don't use with members of (anonymous) unions!
//
#define GLBVAR(x) static auto& x = GPU.x;

View File

@ -57,7 +57,7 @@ enum
uint32 IRQ_GetRegister(unsigned int which, char *special, const uint32 special_len);
void IRQ_SetRegister(unsigned int which, uint32 value);
};
}
#endif

View File

@ -113,7 +113,7 @@ namespace MDFN_IEN_PSX
void PSX_GPULineHook(const pscpu_timestamp_t timestamp, const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider);
uint32 PSX_GetRandU32(uint32 mina, uint32 maxa);
};
}
#include "dis.h"
@ -133,7 +133,7 @@ namespace MDFN_IEN_PSX
extern PS_CDC *CDC;
extern PS_SPU *SPU;
extern MultiAccessSizeMem<2048 * 1024, false> MainRAM;
};
}
enum eRegion
{
@ -453,4 +453,4 @@ EW_EXPORT s32 shock_SetLEC(void* psx, bool enabled);
//whether "determine lag from GPU frames" signal is set (GPU did something considered non-lag)
//returns SHOCK_TRUE or SHOCK_FALSE
EW_EXPORT s32 shock_GetGPUUnlagged(void* psx);
EW_EXPORT s32 shock_GetGPUUnlagged(void* psx);

View File

@ -64,6 +64,18 @@
#include <atomic>
#ifdef __ARM_NEON__
#include <arm_neon.h>
#endif
#ifdef __MMX__
#include <mmintrin.h>
#endif
#ifdef __SSE__
#include <xmmintrin.h>
#endif
namespace MDFN_TESTS_CPP
{
@ -733,6 +745,68 @@ void NO_INLINE NO_CLONE TestGCC70941(void)
assert(tmp == -1);
}
void NO_INLINE NO_CLONE TestGCC71488_Sub(long long* p, int v)
{
for(unsigned i = 0; i < 4; i++)
p[i] = ((!p[4]) > (unsigned)!v) + !p[4];
}
void NO_INLINE NO_CLONE TestGCC71488(void)
{
long long p[5] = { 0, 0, 0, 0, 0 };
TestGCC71488_Sub(p, 1);
assert(p[0] == 2 && p[1] == 2 && p[2] == 2 && p[3] == 2 && p[4] == 0);
}
int NO_INLINE NO_CLONE TestGCC80631_Sub(int* p)
{
int ret = -1;
for(int i = 0; i < 8; i++)
if(p[i])
ret = i;
return ret;
}
void NO_INLINE NO_CLONE TestGCC80631(void)
{
int p[32];
for(int i = 0; i < 32; i++)
p[i] = (i == 0 || i >= 8);
assert(TestGCC80631_Sub(p) == 0);
}
NO_INLINE NO_CLONE void TestGCC81740_Sub(int* p, unsigned count)
{
static const int good[20] = { 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 10, 5, 6, 7, 8, 15, 10, 11, 12, 13 };
assert(count == 20);
for(unsigned i = 0; i < count; i++)
assert(good[i] == p[i]);
}
int TestGCC81740_b;
NO_INLINE NO_CLONE void TestGCC81740(void)
{
int v[4][5] = { 0 };
for(unsigned i = 0; i < sizeof(v) / sizeof(int); i++)
(&v[0][0])[i] = i;
for(int a = 3; a >= 0; a--)
for(TestGCC81740_b = 0; TestGCC81740_b < 3; TestGCC81740_b++)
v[TestGCC81740_b + 1][a + 1] = v[TestGCC81740_b][a];
TestGCC81740_Sub(&v[0][0], sizeof(v) / sizeof(int));
}
template<typename A, typename B>
void NO_INLINE NO_CLONE TestSUCompare_Sub(A a, B b)
{
@ -763,45 +837,84 @@ void NO_INLINE NO_CLONE TestSUCompare(void)
TestSUCompare_Sub<int8, uint8>(TestSUCompare_x0, 255);
}
template<typename T>
NO_INLINE NO_CLONE void CheckAlignasType_Sub(void* p)
{
assert(((uintptr_t)p % alignof(T)) == 0);
}
template<size_t I>
NO_INLINE NO_CLONE void CheckAlignasI_Sub(void* p)
{
assert(((uintptr_t)p % I) == 0);
}
template<typename T>
NO_INLINE NO_CLONE void CheckAlignasType(void)
{
alignas(alignof(T)) uint8 lv0[sizeof(T) + 1];
alignas(alignof(T)) uint8 lv1[sizeof(T) + 1];
alignas(alignof(T)) static uint8 gv0[sizeof(T) + 1];
alignas(alignof(T)) static uint8 gv1[sizeof(T) + 1];
CheckAlignasType_Sub<T>((void*)lv0);
CheckAlignasType_Sub<T>((void*)lv1);
CheckAlignasType_Sub<T>((void*)gv0);
CheckAlignasType_Sub<T>((void*)gv1);
}
template<size_t I>
NO_INLINE NO_CLONE void CheckAlignasI(void)
{
alignas(I) uint8 lv0[I + 1];
alignas(I) uint8 lv1[I + 1];
alignas(I) static uint8 gv0[I + 1];
alignas(I) static uint8 gv1[I + 1];
CheckAlignasI_Sub<I>((void*)lv0);
CheckAlignasI_Sub<I>((void*)lv1);
CheckAlignasI_Sub<I>((void*)gv0);
CheckAlignasI_Sub<I>((void*)gv1);
}
static void DoAlignmentChecks(void)
{
uint8 padding0[3];
alignas(16) uint8 aligned0[7];
alignas(4) uint8 aligned1[2];
alignas(16) uint32 aligned2[2];
uint8 padding1[3];
static_assert(alignof(uint8) <= sizeof(uint8), "Alignment of type is greater than size of type.");
static_assert(alignof(uint16) <= sizeof(uint16), "Alignment of type is greater than size of type.");
static_assert(alignof(uint32) <= sizeof(uint32), "Alignment of type is greater than size of type.");
static_assert(alignof(uint64) <= sizeof(uint64), "Alignment of type is greater than size of type.");
static uint8 g_padding0[3];
alignas(16) static uint8 g_aligned0[7];
alignas(4) static uint8 g_aligned1[2];
alignas(16) static uint32 g_aligned2[2];
static uint8 g_padding1[3];
CheckAlignasType<uint16>();
CheckAlignasType<uint32>();
CheckAlignasType<uint64>();
CheckAlignasType<float>();
CheckAlignasType<double>();
// Make sure compiler doesn't removing padding vars
assert((&padding0[1] - &padding0[0]) == 1);
assert((&padding1[1] - &padding1[0]) == 1);
assert((&g_padding0[1] - &g_padding0[0]) == 1);
assert((&g_padding1[1] - &g_padding1[0]) == 1);
#if defined(ARCH_X86)
CheckAlignasI<16>();
#endif
#if defined(__MMX__)
CheckAlignasType<__m64>();
#endif
assert( (((unsigned long long)&aligned0[0]) & 0xF) == 0);
assert( (((unsigned long long)&aligned1[0]) & 0x3) == 0);
assert( (((unsigned long long)&aligned2[0]) & 0xF) == 0);
#if defined(__SSE__)
CheckAlignasType<__m128>();
#endif
assert(((uint8 *)&aligned0[1] - (uint8 *)&aligned0[0]) == 1);
assert(((uint8 *)&aligned1[1] - (uint8 *)&aligned1[0]) == 1);
assert(((uint8 *)&aligned2[1] - (uint8 *)&aligned2[0]) == 4);
#if defined(ARCH_POWERPC_ALTIVEC)
CheckAlignasType<vector unsigned int>();
CheckAlignasType<vector unsigned short>();
#endif
assert( (((unsigned long long)&g_aligned0[0]) & 0xF) == 0);
assert( (((unsigned long long)&g_aligned1[0]) & 0x3) == 0);
assert( (((unsigned long long)&g_aligned2[0]) & 0xF) == 0);
assert(((uint8 *)&g_aligned0[1] - (uint8 *)&g_aligned0[0]) == 1);
assert(((uint8 *)&g_aligned1[1] - (uint8 *)&g_aligned1[0]) == 1);
assert(((uint8 *)&g_aligned2[1] - (uint8 *)&g_aligned2[0]) == 4);
#ifdef __ARM_NEON__
CheckAlignasType<int16x4_t>();
CheckAlignasType<int32x4_t>();
CheckAlignasType<float32x4_t>();
#endif
}
static uint32 NO_INLINE NO_CLONE RunMASMemTests_DoomAndGloom(uint32 offset)
{
MultiAccessSizeMem<4, false> mt0;
@ -923,6 +1036,48 @@ static void NO_INLINE NO_CLONE RunMiscEndianTests(uint32 arg0, uint32 arg1)
assert(mem16[3] == 0x5566);
assert(mem16[2] == 0x3344);
{
uint64 v64 = 0xDEADBEEFCAFEBABEULL;
for(unsigned i = 0; i < 8; i++)
{
if(!(i & 0x7))
{
assert(ne64_rbo_be<uint64>(&v64, i) == v64);
assert(ne64_rbo_le<uint64>(&v64, i) == v64);
}
if(!(i & 0x3))
{
assert(ne64_rbo_be<uint32>(&v64, i) == (uint32)(v64 >> (32 - i * 8)));
assert(ne64_rbo_le<uint32>(&v64, i) == (uint32)(v64 >> (i * 8)));
}
if(!(i & 0x1))
{
assert(ne64_rbo_be<uint16>(&v64, i) == (uint16)(v64 >> (48 - i * 8)));
assert(ne64_rbo_le<uint16>(&v64, i) == (uint16)(v64 >> (i * 8)));
}
assert(ne64_rbo_be<uint8>(&v64, i) == (uint8)(v64 >> (56 - i * 8)));
assert(ne64_rbo_le<uint8>(&v64, i) == (uint8)(v64 >> (i * 8)));
}
ne64_wbo_be<uint64>(&v64, 0, 0xCAFEBABEDEADBEEF);
assert(v64 == 0xCAFEBABEDEADBEEF);
ne64_wbo_le<uint32>(&v64, 0, 0xD00FDAD0);
ne64_wbo_be<uint16>(&v64, 0, 0xF00D);
uint8 z[2] = { 0xC0, 0xBB };
ne64_rwbo_be<uint8, true>(&v64, 2, &z[0]);
ne64_rwbo_le<uint8, true>(&v64, 4, &z[1]);
ne64_rwbo_le<uint8, false>(&v64, 5, &z[0]);
ne64_rwbo_be<uint8, false>(&v64, 3, &z[1]);
assert(z[0] == 0xC0 && z[1] == 0xBB);
assert(v64 == 0xF00DC0BBD00FDAD0ULL);
}
//
//
//
@ -1704,6 +1859,9 @@ bool MDFN_RunMathTests(void)
TestGCC60196();
TestGCC69606();
TestGCC70941();
TestGCC71488();
TestGCC80631();
TestGCC81740();
TestModTern();
TestBWNotMask31GTZ();