remove unaligned write for #ifdef i386 (it was technically undefined
behavior and the compiler is now smart enough to turn the more elaborate code into a single store)
This commit is contained in:
parent
a71f28fe6c
commit
0dbac6ba02
58
test/uint.c
58
test/uint.c
@ -1,8 +1,8 @@
|
||||
#include <assert.h>
|
||||
#include <uint16.h>
|
||||
#include <uint32.h>
|
||||
#include <uint64.h>
|
||||
#include <byte.h>
|
||||
#include <libowfat/uint16.h>
|
||||
#include <libowfat/uint32.h>
|
||||
#include <libowfat/uint64.h>
|
||||
#include <libowfat/byte.h>
|
||||
|
||||
int main() {
|
||||
char buf[8];
|
||||
@ -11,36 +11,38 @@ int main() {
|
||||
uint16 a;
|
||||
|
||||
buf[0]=buf[1]=0;
|
||||
uint16_pack_big(buf,0x1234);
|
||||
assert(buf[0]==0x12 && buf[1]==0x34);
|
||||
uint16_pack_big(buf,0xabcd);
|
||||
assert((unsigned char)buf[0]==0xab && (unsigned char)buf[1]==0xcd);
|
||||
uint16_unpack_big(buf,&a);
|
||||
assert(a==0x1234);
|
||||
assert(uint16_read_big(buf)==0x1234);
|
||||
assert(a==0xabcd);
|
||||
assert(uint16_read_big(buf)==0xabcd);
|
||||
|
||||
buf[0]=buf[1]=0;
|
||||
uint16_pack(buf,0x1234);
|
||||
assert(buf[0]==0x34 && buf[1]==0x12);
|
||||
uint16_pack(buf,0xabcd);
|
||||
assert((unsigned char)buf[0]==0xcd && (unsigned char)buf[1]==0xab);
|
||||
uint16_unpack(buf,&a);
|
||||
assert(a==0x1234);
|
||||
assert(uint16_read(buf)==0x1234);
|
||||
assert(a==0xabcd);
|
||||
assert(uint16_read(buf)==0xabcd);
|
||||
}
|
||||
|
||||
{
|
||||
uint32 a;
|
||||
|
||||
buf[0]=buf[1]=buf[2]=buf[3]=0;
|
||||
uint32_pack_big(buf,0x12345678);
|
||||
assert(buf[0]==0x12 && buf[1]==0x34 && buf[2]==0x56 && buf[3]==0x78);
|
||||
uint32_pack_big(buf,0x89abcdef);
|
||||
assert((unsigned char)buf[0]==0x89 && (unsigned char)buf[1]==0xab &&
|
||||
(unsigned char)buf[2]==0xcd && (unsigned char)buf[3]==0xef);
|
||||
uint32_unpack_big(buf,&a);
|
||||
assert(a==0x12345678);
|
||||
assert(uint32_read_big(buf)==0x12345678);
|
||||
assert(a==0x89abcdef);
|
||||
assert(uint32_read_big(buf)==0x89abcdef);
|
||||
|
||||
buf[0]=buf[1]=buf[2]=buf[3]=0;
|
||||
uint32_pack(buf,0x12345678);
|
||||
assert(buf[0]==0x78 && buf[1]==0x56 && buf[2]==0x34 && buf[3]==0x12);
|
||||
uint32_pack(buf,0x89abcdef);
|
||||
assert((unsigned char)buf[3]==0x89 && (unsigned char)buf[2]==0xab &&
|
||||
(unsigned char)buf[1]==0xcd && (unsigned char)buf[0]==0xef);
|
||||
uint32_unpack(buf,&a);
|
||||
assert(a==0x12345678);
|
||||
assert(uint32_read(buf)==0x12345678);
|
||||
assert(a==0x89abcdef);
|
||||
assert(uint32_read(buf)==0x89abcdef);
|
||||
}
|
||||
|
||||
{
|
||||
@ -48,18 +50,18 @@ int main() {
|
||||
unsigned int i;
|
||||
|
||||
byte_zero(buf,sizeof(buf));
|
||||
uint64_pack_big(buf,0x0102030405060708ull);
|
||||
for (i=0; i<8; ++i) assert(buf[i]==i+1);
|
||||
uint64_pack_big(buf,0x8182838485868788ull);
|
||||
for (i=0; i<8; ++i) assert((unsigned char)buf[i]==i+0x81);
|
||||
uint64_unpack_big(buf,&a);
|
||||
assert(a==0x0102030405060708ull);
|
||||
assert(uint64_read_big(buf)==0x0102030405060708ull);
|
||||
assert(a==0x8182838485868788ull);
|
||||
assert(uint64_read_big(buf)==0x8182838485868788ull);
|
||||
|
||||
byte_zero(buf,sizeof(buf));
|
||||
uint64_pack(buf,0x0102030405060708ull);
|
||||
for (i=0; i<8; ++i) assert(buf[7-i]==i+1);
|
||||
uint64_pack(buf,0x8182838485868788ull);
|
||||
for (i=0; i<8; ++i) assert((unsigned char)buf[7-i]==i+0x81);
|
||||
uint64_unpack(buf,&a);
|
||||
assert(a==0x0102030405060708ull);
|
||||
assert(uint64_read(buf)==0x0102030405060708ull);
|
||||
assert(a==0x8182838485868788ull);
|
||||
assert(uint64_read(buf)==0x8182838485868788ull);
|
||||
}
|
||||
|
||||
|
||||
|
36
uint16.h
36
uint16.h
@ -14,42 +14,42 @@ typedef int16_t int16;
|
||||
|
||||
#if (defined(__i386__) || defined(__x86_64__)) && !defined(NO_UINT16_MACROS)
|
||||
|
||||
/* On x86 and x64 unaligned access are OK and the compiler knows it and
|
||||
* will collapse this long-looking code into a single load or store
|
||||
* instruction, so turn it into inline functions */
|
||||
|
||||
static inline void uint16_pack(char* out,uint16 in) {
|
||||
*(uint16*)out=in;
|
||||
out[0]=in;
|
||||
out[1]=in>>8;
|
||||
}
|
||||
|
||||
static inline void uint16_unpack(const char *in,uint16* out) {
|
||||
*out=*(const uint16*)in;
|
||||
const unsigned char* i = (const unsigned char*)in;
|
||||
*out=i[0] | (i[1]<<8);
|
||||
}
|
||||
|
||||
static inline uint16 uint16_read(const char* in) {
|
||||
return *(const uint16*)in;
|
||||
const unsigned char* i = (const unsigned char*)in;
|
||||
return i[0] | (i[1]<<8);
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) && defined(__GNUC__)
|
||||
|
||||
static inline void uint16_pack_big(char* out,uint16 in) {
|
||||
*(uint16*)out=__builtin_bswap16(in);
|
||||
out[0]=in>>8;
|
||||
out[1]=in;
|
||||
}
|
||||
|
||||
static inline void uint16_unpack_big(const char in[2],uint16* out) {
|
||||
*out=__builtin_bswap16(*(const uint16*)in);
|
||||
static inline void uint16_unpack_big(const char *in,uint16* out) {
|
||||
const unsigned char* i = (const unsigned char*)in;
|
||||
*out=(i[0]<<8) | i[1];
|
||||
}
|
||||
|
||||
static inline uint16 uint16_read_big(const char in[2]) {
|
||||
return __builtin_bswap16(*(const uint16*)in);
|
||||
static inline uint16 uint16_read_big(const char* in) {
|
||||
const unsigned char* i = (const unsigned char*)in;
|
||||
return (i[0]<<8) | i[1];
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void uint16_pack_big(char *out,uint16 in);
|
||||
void uint16_unpack_big(const char *in,uint16* out);
|
||||
uint16 uint16_read_big(const char *in);
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
void uint16_pack(char *out,uint16 in);
|
||||
void uint16_pack_big(char *out,uint16 in);
|
||||
void uint16_unpack(const char *in,uint16* out);
|
||||
|
36
uint32.h
36
uint32.h
@ -14,42 +14,46 @@ typedef int32_t int32;
|
||||
|
||||
#if (defined(__i386__) || defined(__x86_64__)) && !defined(NO_UINT32_MACROS)
|
||||
|
||||
/* On x86 and x64 unaligned access are OK and the compiler knows it and
|
||||
* will collapse this long-looking code into a single load or store
|
||||
* instruction, so turn it into inline functions */
|
||||
|
||||
static inline void uint32_pack(char* out,uint32 in) {
|
||||
*(uint32*)out=in;
|
||||
out[0]=in;
|
||||
out[1]=in>>8;
|
||||
out[2]=in>>16;
|
||||
out[3]=in>>24;
|
||||
}
|
||||
|
||||
static inline void uint32_unpack(const char *in,uint32* out) {
|
||||
*out=*(const uint32*)in;
|
||||
const unsigned char* i = (const unsigned char*)in;
|
||||
*out=i[0] | (i[1]<<8) | (i[2]<<16) | (i[3]<<24);
|
||||
}
|
||||
|
||||
static inline uint32 uint32_read(const char* in) {
|
||||
return *(const uint32*)in;
|
||||
const unsigned char* i = (const unsigned char*)in;
|
||||
return i[0] | (i[1]<<8) | (i[2]<<16) | (i[3]<<24);
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) && defined(__GNUC__)
|
||||
|
||||
static inline void uint32_pack_big(char *out,uint32 in) {
|
||||
*(uint32*)out=__builtin_bswap32(in);
|
||||
out[0]=in>>24;
|
||||
out[1]=in>>16;
|
||||
out[2]=in>>8;
|
||||
out[3]=in;
|
||||
}
|
||||
|
||||
static inline void uint32_unpack_big(const char *in,uint32* out) {
|
||||
*out=__builtin_bswap32(*(const uint32*)in);
|
||||
const unsigned char* i = (const unsigned char*)in;
|
||||
*out=(i[0]<<24) | (i[1]<<16) | (i[2]<<8) | i[3];
|
||||
}
|
||||
|
||||
static inline uint32 uint32_read_big(const char *in) {
|
||||
return __builtin_bswap32(*(const uint32*)in);
|
||||
const unsigned char* i = (const unsigned char*)in;
|
||||
return (i[0]<<24) | (i[1]<<16) | (i[2]<<8) | i[3];
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void uint32_pack_big(char *out,uint32 in);
|
||||
void uint32_unpack_big(const char *in,uint32* out);
|
||||
uint32 uint32_read_big(const char *in);
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
void uint32_pack(char *out,uint32 in);
|
||||
void uint32_pack_big(char *out,uint32 in);
|
||||
void uint32_unpack(const char *in,uint32* out);
|
||||
|
61
uint64.h
61
uint64.h
@ -13,12 +13,61 @@ typedef uint64_t uint64;
|
||||
typedef int64_t int64;
|
||||
|
||||
#if (defined(__i386__) || defined(__x86_64__)) && !defined(NO_UINT64_MACROS)
|
||||
#define uint64_pack(out,in) (*(uint64*)(out)=(in))
|
||||
#define uint64_unpack(in,out) (*(out)=*(uint64*)(in))
|
||||
#define uint64_read(in) (*(uint64*)(in))
|
||||
void uint64_pack_big(char *out,uint64 in);
|
||||
void uint64_unpack_big(const char *in,uint64* out);
|
||||
uint64 uint64_read_big(const char *in);
|
||||
|
||||
/* On x86 and x64 unaligned access are OK and the compiler knows it and
|
||||
* will collapse this long-looking code into a single load or store
|
||||
* instruction, so turn it into inline functions */
|
||||
|
||||
static inline void uint64_pack(char* out,uint64 in) {
|
||||
out[0]=in;
|
||||
out[1]=in>>8;
|
||||
out[2]=in>>16;
|
||||
out[3]=in>>24;
|
||||
out[4]=in>>32;
|
||||
out[5]=in>>40;
|
||||
out[6]=in>>48;
|
||||
out[7]=in>>56;
|
||||
}
|
||||
|
||||
static inline void uint64_unpack(const char *in,uint64* out) {
|
||||
const unsigned char* i = (const unsigned char*)in;
|
||||
*out=i[0] | (i[1]<<8) | (i[2]<<16) | ((uint64)i[3]<<24) |
|
||||
((uint64)i[4]<<32) | ((uint64)i[5]<<40) |
|
||||
((uint64)i[6]<<48) | ((uint64)i[7]<<56);
|
||||
}
|
||||
|
||||
static inline uint64 uint64_read(const char *in) {
|
||||
const unsigned char* i = (const unsigned char*)in;
|
||||
return i[0] | (i[1]<<8) | (i[2]<<16) | ((uint64)i[3]<<24) |
|
||||
((uint64)i[4]<<32) | ((uint64)i[5]<<40) |
|
||||
((uint64)i[6]<<48) | ((uint64)i[7]<<56);
|
||||
}
|
||||
|
||||
static inline void uint64_pack_big(char *out,uint64 in) {
|
||||
out[0]=in>>56;
|
||||
out[1]=in>>48;
|
||||
out[2]=in>>40;
|
||||
out[3]=in>>32;
|
||||
out[4]=in>>24;
|
||||
out[5]=in>>16;
|
||||
out[6]=in>>8;
|
||||
out[7]=in;
|
||||
}
|
||||
|
||||
static inline void uint64_unpack_big(const char *in,uint64* out) {
|
||||
const unsigned char* i = (const unsigned char*)in;
|
||||
*out=(i[7] | (i[6]<<8) | (i[5]<<16) | ((uint64)(i[4])<<24)) |
|
||||
((uint64)(i[3])<<32) | ((uint64)(i[2])<<40) |
|
||||
((uint64)(i[1])<<48) | ((uint64)(i[0])<<56);
|
||||
}
|
||||
|
||||
static inline uint64 uint64_read_big(const char *in) {
|
||||
const unsigned char* i = (const unsigned char*)in;
|
||||
return (i[7] | (i[6]<<8) | (i[5]<<16) | ((uint64)(i[4])<<24)) |
|
||||
((uint64)(i[3])<<32) | ((uint64)(i[2])<<40) |
|
||||
((uint64)(i[1])<<48) | ((uint64)(i[0])<<56);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void uint64_pack(char *out,uint64 in);
|
||||
|
Loading…
x
Reference in New Issue
Block a user