1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
/* Copyright (C) 2022 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* byte order (endianness) support routines.
*/
#ifndef INCLUDED_BYTE_ORDER
#define INCLUDED_BYTE_ORDER
#include "lib/sysdep/cpu.h"
// detect byte order via predefined macros.
#ifndef BYTE_ORDER
# define LITTLE_ENDIAN 0x4321
# define BIG_ENDIAN 0x1234
# if ARCH_IA32 || ARCH_IA64 || ARCH_AMD64 || ARCH_ALPHA || ARCH_ARM || ARCH_AARCH64 || ARCH_MIPS || ARCH_E2K || ARCH_PPC64 || defined(__LITTLE_ENDIAN__)
# define BYTE_ORDER LITTLE_ENDIAN
# else
# define BYTE_ORDER BIG_ENDIAN
# endif
#endif
/**
* convert 4 characters to u32 (at compile time) for easy comparison.
* output is in native byte order; e.g. FOURCC_LE can be used instead.
**/
#define FOURCC(a,b,c,d) // real definition is below
#undef FOURCC
// implementation rationale:
// - can't pass code as string, and use s[0]..s[3], because
// VC6/7 don't realize the macro is constant
// (it should be usable as a switch{} expression)
// - the casts are ugly but necessary. u32 is required because u8 << 8 == 0;
// the additional u8 cast ensures each character is treated as unsigned
// (otherwise, they'd be promoted to signed int before the u32 cast,
// which would break things).
/// big-endian version of FOURCC
#define FOURCC_BE(a,b,c,d) ( ((u32)(u8)a) << 24 | ((u32)(u8)b) << 16 | \
((u32)(u8)c) << 8 | ((u32)(u8)d) << 0 )
/// little-endian version of FOURCC
#define FOURCC_LE(a,b,c,d) ( ((u32)(u8)a) << 0 | ((u32)(u8)b) << 8 | \
((u32)(u8)c) << 16 | ((u32)(u8)d) << 24 )
#if BYTE_ORDER == BIG_ENDIAN
# define FOURCC FOURCC_BE
#else
# define FOURCC FOURCC_LE
#endif
#if BYTE_ORDER == BIG_ENDIAN
// convert a little-endian number to/from native byte order.
# define to_le16(x) swap16(x)
# define to_le32(x) swap32(x)
# define to_le64(x) swap64(x)
// convert a big-endian number to/from native byte order.
# define to_be16(x) (x)
# define to_be32(x) (x)
# define to_be64(x) (x)
#else // LITTLE_ENDIAN
// convert a little-endian number to/from native byte order.
# define to_le16(x) (x)
# define to_le32(x) (x)
# define to_le64(x) (x)
// convert a big-endian number to/from native byte order.
# define to_be16(x) swap16(x)
# define to_be32(x) swap32(x)
# define to_be64(x) swap64(x)
#endif
/// read a little-endian number from memory into native byte order.
u16 read_le16(const void* p);
u32 read_le32(const void* p); /// see read_le16
u64 read_le64(const void* p); /// see read_le16
/// read a big-endian number from memory into native byte order.
u16 read_be16(const void* p);
u32 read_be32(const void* p); /// see read_be16
u64 read_be64(const void* p); /// see read_be16
/// write a little-endian number to memory in native byte order.
void write_le16(void* p, u16 x);
void write_le32(void* p, u32 x); /// see write_le16
void write_le64(void* p, u64 x); /// see write_le16
/// write a big-endian number to memory in native byte order.
void write_be16(void* p, u16 x);
void write_be32(void* p, u32 x); /// see write_be16
void write_be64(void* p, u64 x); /// see write_be16
/**
* zero-extend \<size\> (truncated to 8) bytes of little-endian data to u64,
* starting at address \<p\> (need not be aligned).
**/
u64 movzx_le64(const u8* p, size_t size);
u64 movzx_be64(const u8* p, size_t size);
/**
* sign-extend \<size\> (truncated to 8) bytes of little-endian data to i64,
* starting at address \<p\> (need not be aligned).
**/
i64 movsx_le64(const u8* p, size_t size);
i64 movsx_be64(const u8* p, size_t size);
#if ICC_VERSION
#define swap32 _bswap
#define swap64 _bswap64
#elif MSC_VERSION
extern unsigned short _byteswap_ushort(unsigned short);
extern unsigned long _byteswap_ulong(unsigned long);
extern unsigned __int64 _byteswap_uint64(unsigned __int64);
#pragma intrinsic(_byteswap_ushort)
#pragma intrinsic(_byteswap_ulong)
#pragma intrinsic(_byteswap_uint64)
# define swap16 _byteswap_ushort
# define swap32 _byteswap_ulong
# define swap64 _byteswap_uint64
#elif defined(linux)
# include <asm/byteorder.h>
# if defined(__arch__swab16) && !defined(swap16)
# define swap16 __arch__swab16
# endif
# if defined(__arch__swab32) && !defined(swap32)
# define swap32 __arch__swab32
# endif
# if defined(__arch__swab64) && !defined(swap64)
# define swap64 __arch__swab64
# endif
#endif
#ifndef swap16
u16 swap16(const u16 x);
#endif
#ifndef swap32
u32 swap32(const u32 x);
#endif
#ifndef swap64
u64 swap64(const u64 x);
#endif
#endif // #ifndef INCLUDED_BYTE_ORDER
|