update to 0.9.48
This commit is contained in:
parent
79e4e0690b
commit
7cfdc91e1f
|
@ -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
|
|
@ -137,3 +137,5 @@ char (*BLAHBLAHBLAH( UNALIGNED T (&)[N] ))[N];
|
|||
#else
|
||||
#define EW_PACKED( ... ) __VA_ARGS__ __attribute__((__packed__))
|
||||
#endif
|
||||
|
||||
#define MDFN_IS_BIGENDIAN 0
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue