diff options
author | Yves Orton <demerphq@gmail.com> | 2019-11-06 00:05:17 +0100 |
---|---|---|
committer | Yves Orton <demerphq@gmail.com> | 2019-11-06 00:05:17 +0100 |
commit | ed16b18d62c264e7e9331ea67931b66b7d976bb9 (patch) | |
tree | cfc54ada5ae9b26a3151749bc09636402da3fd9a /hv_macro.h | |
parent | 783bd734e8c8eb06c400a471004e329244ef995f (diff) | |
download | perl-ed16b18d62c264e7e9331ea67931b66b7d976bb9.tar.gz |
rework U8TOxx_LE macros to force unsigned access
This introduces a _shifted_octet() utility macro to make things
more clear, it also adds support for USE_UNALIGNED_PTR_DEREF for
little-endian platforms that allow unaligned access. This must
be manually defined and ONLY affects little endian builds currently,
and is there primarily for -g builds on x86 (eg for perl developers
themselves).
Diffstat (limited to 'hv_macro.h')
-rw-r--r-- | hv_macro.h | 64 |
1 files changed, 47 insertions, 17 deletions
diff --git a/hv_macro.h b/hv_macro.h index d6d9e8a304..dee83253d0 100644 --- a/hv_macro.h +++ b/hv_macro.h @@ -5,6 +5,15 @@ #define CAN64BITHASH #endif +#ifdef CAN64BITHASH + #ifndef U64TYPE + /* This probably isn't going to work, but failing with a compiler error due to + lack of uint64_t is no worse than failing right now with an #error. */ + #define U64 uint64_t + #endif +#endif + + /*----------------------------------------------------------------------------- * Endianess and util macros * @@ -21,26 +30,47 @@ */ #ifndef U8TO16_LE + #define _shifted_octet(type,ptr,idx,shift) (((type)(((U8*)ptr)[idx]))<<shift) #if (BYTEORDER == 0x1234 || BYTEORDER == 0x12345678) - #define U8TO16_LE(ptr) ((U32)(ptr)[0]|(U32)(ptr)[1]<<8) - #define U8TO32_LE(ptr) ((U32)(ptr)[0]|(U32)(ptr)[1]<<8|(U32)(ptr)[2]<<16|(U32)(ptr)[3]<<24) - #define U8TO64_LE(ptr) ((U64)(ptr)[0]|(U64)(ptr)[1]<<8|(U64)(ptr)[2]<<16|(U64)(ptr)[3]<<24|\ - (U64)(ptr)[4]<<32|(U64)(ptr)[5]<<40|\ - (U64)(ptr)[6]<<48|(U64)(ptr)[7]<<56) + #ifdef USE_UNALIGNED_PTR_DEREF + #define U8TO16_LE(ptr) (*((const U16*)(ptr))) + #define U8TO32_LE(ptr) (*((const U32*)(ptr))) + #define U8TO64_LE(ptr) (*((const U64*)(ptr))) + #else + #define U8TO16_LE(ptr) (_shifted_octet(U16,ptr,0, 0)|\ + _shifted_octet(U16,ptr,1, 8)) + + #define U8TO32_LE(ptr) (_shifted_octet(U32,ptr,0, 0)|\ + _shifted_octet(U32,ptr,1, 8)|\ + _shifted_octet(U32,ptr,2,16)|\ + _shifted_octet(U32,ptr,3,24)) + + #define U8TO64_LE(ptr) (_shifted_octet(U64,ptr,0, 0)|\ + _shifted_octet(U64,ptr,1, 8)|\ + _shifted_octet(U64,ptr,2,16)|\ + _shifted_octet(U64,ptr,3,24)|\ + _shifted_octet(U64,ptr,4,32)|\ + _shifted_octet(U64,ptr,5,40)|\ + _shifted_octet(U64,ptr,6,48)|\ + _shifted_octet(U64,ptr,7,56)) + #endif #elif (BYTEORDER == 0x4321 || BYTEORDER == 0x87654321) - #define U8TO16_LE(ptr) ((U32)(ptr)[1]|(U32)(ptr)[0]<<8) - #define U8TO32_LE(ptr) ((U32)(ptr)[3]|(U32)(ptr)[2]<<8|(U32)(ptr)[1]<<16|(U32)(ptr)[0]<<24) - #define U8TO64_LE(ptr) ((U64)(ptr)[7]|(U64)(ptr)[6]<<8|(U64)(ptr)[5]<<16|(U64)(ptr)[4]<<24|\ - (U64)(ptr)[3]<<32|(U64)(ptr)[2]<<40|\ - (U64)(ptr)[1]<<48|(U64)(ptr)[0]<<56) - #endif -#endif + #define U8TO16_LE(ptr) (_shifted_octet(U16,ptr,1, 0)|\ + _shifted_octet(U16,ptr,0, 8)) -#ifdef CAN64BITHASH - #ifndef U64TYPE - /* This probably isn't going to work, but failing with a compiler error due to - lack of uint64_t is no worse than failing right now with an #error. */ - #define U64 uint64_t + #define U8TO32_LE(ptr) (_shifted_octet(U32,ptr,3, 0)|\ + _shifted_octet(U32,ptr,2, 8)|\ + _shifted_octet(U32,ptr,1,16)|\ + _shifted_octet(U32,ptr,0,24)) + + #define U8TO64_LE(ptr) (_shifted_octet(U64,ptr,7, 0)|\ + _shifted_octet(U64,ptr,6, 8)|\ + _shifted_octet(U64,ptr,5,16)|\ + _shifted_octet(U64,ptr,4,24)|\ + _shifted_octet(U64,ptr,3,32)|\ + _shifted_octet(U64,ptr,2,40)|\ + _shifted_octet(U64,ptr,1,48)|\ + _shifted_octet(U64,ptr,0,56)) #endif #endif |