This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
rework U8TOxx_LE macros to force unsigned access
[perl5.git] / hv_macro.h
CommitLineData
1c4b2386
YO
1#ifndef PERL_SEEN_HV_MACRO_H /* compile once */
2#define PERL_SEEN_HV_MACRO_H
3
4#if IVSIZE == 8
5#define CAN64BITHASH
6#endif
7
ed16b18d
YO
8#ifdef CAN64BITHASH
9 #ifndef U64TYPE
10 /* This probably isn't going to work, but failing with a compiler error due to
11 lack of uint64_t is no worse than failing right now with an #error. */
12 #define U64 uint64_t
13 #endif
14#endif
15
16
1c4b2386 17/*-----------------------------------------------------------------------------
e8864dba 18 * Endianess and util macros
1c4b2386
YO
19 *
20 * The following 3 macros are defined in this section. The other macros defined
21 * are only needed to help derive these 3.
22 *
23 * U8TO16_LE(x) Read a little endian unsigned 32-bit int
24 * U8TO32_LE(x) Read a little endian unsigned 32-bit int
25 * U8TO28_LE(x) Read a little endian unsigned 32-bit int
26 * ROTL32(x,r) Rotate x left by r bits
27 * ROTL64(x,r) Rotate x left by r bits
28 * ROTR32(x,r) Rotate x right by r bits
29 * ROTR64(x,r) Rotate x right by r bits
30 */
31
e8864dba 32#ifndef U8TO16_LE
ed16b18d 33 #define _shifted_octet(type,ptr,idx,shift) (((type)(((U8*)ptr)[idx]))<<shift)
1c4b2386 34 #if (BYTEORDER == 0x1234 || BYTEORDER == 0x12345678)
ed16b18d
YO
35 #ifdef USE_UNALIGNED_PTR_DEREF
36 #define U8TO16_LE(ptr) (*((const U16*)(ptr)))
37 #define U8TO32_LE(ptr) (*((const U32*)(ptr)))
38 #define U8TO64_LE(ptr) (*((const U64*)(ptr)))
39 #else
40 #define U8TO16_LE(ptr) (_shifted_octet(U16,ptr,0, 0)|\
41 _shifted_octet(U16,ptr,1, 8))
42
43 #define U8TO32_LE(ptr) (_shifted_octet(U32,ptr,0, 0)|\
44 _shifted_octet(U32,ptr,1, 8)|\
45 _shifted_octet(U32,ptr,2,16)|\
46 _shifted_octet(U32,ptr,3,24))
47
48 #define U8TO64_LE(ptr) (_shifted_octet(U64,ptr,0, 0)|\
49 _shifted_octet(U64,ptr,1, 8)|\
50 _shifted_octet(U64,ptr,2,16)|\
51 _shifted_octet(U64,ptr,3,24)|\
52 _shifted_octet(U64,ptr,4,32)|\
53 _shifted_octet(U64,ptr,5,40)|\
54 _shifted_octet(U64,ptr,6,48)|\
55 _shifted_octet(U64,ptr,7,56))
56 #endif
783bd734 57 #elif (BYTEORDER == 0x4321 || BYTEORDER == 0x87654321)
ed16b18d
YO
58 #define U8TO16_LE(ptr) (_shifted_octet(U16,ptr,1, 0)|\
59 _shifted_octet(U16,ptr,0, 8))
1c4b2386 60
ed16b18d
YO
61 #define U8TO32_LE(ptr) (_shifted_octet(U32,ptr,3, 0)|\
62 _shifted_octet(U32,ptr,2, 8)|\
63 _shifted_octet(U32,ptr,1,16)|\
64 _shifted_octet(U32,ptr,0,24))
65
66 #define U8TO64_LE(ptr) (_shifted_octet(U64,ptr,7, 0)|\
67 _shifted_octet(U64,ptr,6, 8)|\
68 _shifted_octet(U64,ptr,5,16)|\
69 _shifted_octet(U64,ptr,4,24)|\
70 _shifted_octet(U64,ptr,3,32)|\
71 _shifted_octet(U64,ptr,2,40)|\
72 _shifted_octet(U64,ptr,1,48)|\
73 _shifted_octet(U64,ptr,0,56))
1c4b2386
YO
74 #endif
75#endif
76
77/* Find best way to ROTL32/ROTL64 */
78#if defined(_MSC_VER)
79 #include <stdlib.h> /* Microsoft put _rotl declaration in here */
80 #define ROTL32(x,r) _rotl(x,r)
81 #define ROTR32(x,r) _rotr(x,r)
82 #define ROTL64(x,r) _rotl64(x,r)
83 #define ROTR64(x,r) _rotr64(x,r)
84#else
85 /* gcc recognises this code and generates a rotate instruction for CPUs with one */
86 #define ROTL32(x,r) (((U32)(x) << (r)) | ((U32)(x) >> (32 - (r))))
87 #define ROTR32(x,r) (((U32)(x) << (32 - (r))) | ((U32)(x) >> (r)))
88 #define ROTL64(x,r) ( ( (U64)(x) << (r) ) | ( (U64)(x) >> ( 64 - (r) ) ) )
89 #define ROTR64(x,r) ( ( (U64)(x) << ( 64 - (r) ) ) | ( (U64)(x) >> (r) ) )
90#endif
91
92
93#ifdef UV_IS_QUAD
94#define ROTL_UV(x,r) ROTL64(x,r)
95#define ROTR_UV(x,r) ROTL64(x,r)
96#else
97#define ROTL_UV(x,r) ROTL32(x,r)
98#define ROTR_UV(x,r) ROTR32(x,r)
99#endif
100#if IVSIZE == 8
101#define CAN64BITHASH
102#endif
103
104#endif