diff options
| -rw-r--r-- | common/endian.h | 101 | 
1 files changed, 53 insertions, 48 deletions
| diff --git a/common/endian.h b/common/endian.h index 9a6c0cd42c..9f10b63053 100644 --- a/common/endian.h +++ b/common/endian.h @@ -71,64 +71,36 @@  	((uint16)((((a) >>  8) & 0x00FF) | \  	          (((a) <<  8) & 0xFF00) )) -#ifdef HAVE_INT64 + +  /** - * Swap the bytes in a 64 bit word in order to convert LE encoded data to BE + * Swap the bytes in a 16 bit word in order to convert LE encoded data to BE   * and vice versa.   */ -// machine/compiler-specific variants come first, fallback last +// compilerspecific variants come first, fallback last  // Test for GCC and if the target has the MIPS rel.2 instructions (we know the psp does) -// -// TODO: Fix this #if statement. It isn't changed from 32 bit. Is there a 64 bit swap instruction?  #if defined(__GNUC__) && (defined(__psp__) || defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)) -	FORCEINLINE uint32 SWAP_BYTES_32(const uint32 a) { +	FORCEINLINE uint16 SWAP_BYTES_16(const uint16 a) {  		if (__builtin_constant_p(a)) { -			return SWAP_CONSTANT_32(a); +			return SWAP_CONSTANT_16(a);  		} else { -			uint32 result; -#	if defined(__psp__) -			// use special allegrex instruction -			__asm__ ("wsbw %0,%1" : "=r" (result) : "r" (a)); -#	else -			__asm__ ("wsbh %0,%1\n" -			         "rotr %0,%0,16" : "=r" (result) : "r" (a)); -#	endif +			uint16 result; +			__asm__ ("wsbh %0,%1" : "=r" (result) : "r" (a));  			return result;  		}  	} - -// Test for GCC >= 4.3.0 as this version added the bswap builtin -#elif GCC_ATLEAST(4, 3) - -	FORCEINLINE uint64 SWAP_BYTES_64(uint64 a) { -		return __builtin_bswap64(a); -	} - -#elif defined(_MSC_VER) - -	FORCEINLINE uint64 SWAP_BYTES_64(uint64 a) { -		return _byteswap_uint64(a); -	} - -// generic fallback  #else -	inline uint64 SWAP_BYTES_64(uint64 a) { -		uint32 low = (uint32)a, high = (uint32)(a >> 32); -		uint16 lowLow = (uint16)low, lowHigh = (uint16)(low >> 16), -		       highLow = (uint16)high, highHigh = (uint16)(high >> 16); - -		return ((uint64)(((uint32)(uint16)((lowLow   >> 8) | (lowLow   << 8)) << 16) | -		                          (uint16)((lowHigh  >> 8) | (lowHigh  << 8))) << 32) | -		                (((uint32)(uint16)((highLow  >> 8) | (highLow  << 8)) << 16) | -		                          (uint16)((highHigh >> 8) | (highHigh << 8))); +	inline uint16 SWAP_BYTES_16(const uint16 a) { +		return (a >> 8) | (a << 8);  	}  #endif -#endif // HAVE_INT64 + +  /**   * Swap the bytes in a 32 bit word in order to convert LE encoded data to BE   * and vice versa. @@ -178,32 +150,65 @@  	}  #endif +#ifdef HAVE_INT64  /** - * Swap the bytes in a 16 bit word in order to convert LE encoded data to BE + * Swap the bytes in a 64 bit word in order to convert LE encoded data to BE   * and vice versa.   */ -// compilerspecific variants come first, fallback last +// machine/compiler-specific variants come first, fallback last  // Test for GCC and if the target has the MIPS rel.2 instructions (we know the psp does) +// +// TODO: Fix this #if statement. It isn't changed from 32 bit. Is there a 64 bit swap instruction?  #if defined(__GNUC__) && (defined(__psp__) || defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)) -	FORCEINLINE uint16 SWAP_BYTES_16(const uint16 a) { +	FORCEINLINE uint32 SWAP_BYTES_32(const uint32 a) {  		if (__builtin_constant_p(a)) { -			return SWAP_CONSTANT_16(a); +			return SWAP_CONSTANT_32(a);  		} else { -			uint16 result; -			__asm__ ("wsbh %0,%1" : "=r" (result) : "r" (a)); +			uint32 result; +#	if defined(__psp__) +			// use special allegrex instruction +			__asm__ ("wsbw %0,%1" : "=r" (result) : "r" (a)); +#	else +			__asm__ ("wsbh %0,%1\n" +			         "rotr %0,%0,16" : "=r" (result) : "r" (a)); +#	endif  			return result;  		}  	} + +// Test for GCC >= 4.3.0 as this version added the bswap builtin +#elif GCC_ATLEAST(4, 3) + +	FORCEINLINE uint64 SWAP_BYTES_64(uint64 a) { +		return __builtin_bswap64(a); +	} + +#elif defined(_MSC_VER) + +	FORCEINLINE uint64 SWAP_BYTES_64(uint64 a) { +		return _byteswap_uint64(a); +	} + +// generic fallback  #else -	inline uint16 SWAP_BYTES_16(const uint16 a) { -		return (a >> 8) | (a << 8); +	inline uint64 SWAP_BYTES_64(uint64 a) { +		uint32 low = (uint32)a, high = (uint32)(a >> 32); +		uint16 lowLow = (uint16)low, lowHigh = (uint16)(low >> 16), +		       highLow = (uint16)high, highHigh = (uint16)(high >> 16); + +		return ((uint64)(((uint32)(uint16)((lowLow   >> 8) | (lowLow   << 8)) << 16) | +		                          (uint16)((lowHigh  >> 8) | (lowHigh  << 8))) << 32) | +		                (((uint32)(uint16)((highLow  >> 8) | (highLow  << 8)) << 16) | +		                          (uint16)((highHigh >> 8) | (highHigh << 8)));  	}  #endif +#endif // HAVE_INT64 +  /**   * A wrapper macro used around four character constants, like 'DATA', to | 
