xref: /reactos/sdk/include/reactos/unaligned.h (revision 53b304e6)
1 /*
2  * PROJECT:     ReactOS SDK
3  * LICENSE:     MIT (https://spdx.org/licenses/MIT)
4  * PURPOSE:     Unaligened access helper functions
5  * COPYRIGHT:   Copyright 2024 Timo Kreuzer <timo.kreuzer@reactos.org>
6  */
7 
8 #pragma once
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 #if defined(_M_IX86) || defined(_M_AMD64)
15 #define _UNALIGNED_ACCESS_ALLOWED 1
16 #else // defined(_M_IX86) || defined(_M_AMD64)
17 #define _UNALIGNED_ACCESS_ALLOWED 0
18 #endif // defined(_M_IX86) || defined(_M_AMD64)
19 
20 #if _UNALIGNED_ACCESS_ALLOWED
21 
22 __forceinline
23 unsigned short
ReadUnalignedU16(const unsigned short * p)24 ReadUnalignedU16(const unsigned short* p)
25 {
26     return *p;
27 }
28 
29 __forceinline
30 unsigned long
ReadUnalignedU32(const unsigned long * p)31 ReadUnalignedU32(const unsigned long* p)
32 {
33     return *p;
34 }
35 
36 __forceinline
37 unsigned long long
ReadUnalignedU64(const unsigned long long * p)38 ReadUnalignedU64(const unsigned long long* p)
39 {
40     return *p;
41 }
42 
43 __forceinline
44 void
WriteUnalignedU16(unsigned short * p,unsigned short val)45 WriteUnalignedU16(unsigned short* p, unsigned short val)
46 {
47     *p = val;
48 }
49 
50 __forceinline
51 void
WriteUnalignedU32(unsigned long * p,unsigned long val)52 WriteUnalignedU32(unsigned long* p, unsigned long val)
53 {
54     *p = val;
55 }
56 
57 __forceinline
58 void
WriteUnalignedU64(unsigned long long * p,unsigned long long val)59 WriteUnalignedU64(unsigned long long* p, unsigned long long val)
60 {
61     *p = val;
62 }
63 
64 #else // !UNALIGNED_ACCESS_ALLOWED
65 
66 __forceinline
67 unsigned short
68 ReadUnalignedU16(const unsigned short* p)
69 {
70     unsigned char* p1 = (unsigned char*)p;
71     return (unsigned short)(p1[0] | (p1[1] << 8));
72 }
73 
74 __forceinline
75 unsigned long
76 ReadUnalignedU32(const unsigned long* p)
77 {
78     unsigned char* p1 = (unsigned char*)p;
79     return (((unsigned long)p1[0] << 0) |
80             ((unsigned long)p1[1] << 8) |
81             ((unsigned long)p1[2] << 16) |
82             ((unsigned long)p1[3] << 24));
83 }
84 
85 __forceinline
86 unsigned long long
87 ReadUnalignedU64(const unsigned long long* p)
88 {
89     unsigned char* p1 = (unsigned char*)p;
90     return (((unsigned long long)p1[0] << 0)  |
91             ((unsigned long long)p1[1] << 8)  |
92             ((unsigned long long)p1[2] << 16) |
93             ((unsigned long long)p1[3] << 24) |
94             ((unsigned long long)p1[4] << 32) |
95             ((unsigned long long)p1[5] << 40) |
96             ((unsigned long long)p1[6] << 48) |
97          ((unsigned long long)p1[7] << 56));
98 }
99 
100 __forceinline
101 void
102 WriteUnalignedU16(unsigned short* p, unsigned short val)
103 {
104     unsigned char* p1 = (unsigned char*)p;
105     p1[0] = (unsigned char)(val >> 0);
106     p1[1] = (unsigned char)(val >> 8);
107 }
108 
109 __forceinline
110 void
111 WriteUnalignedU32(unsigned long* p, unsigned long val)
112 {
113     unsigned char* p1 = (unsigned char*)p;
114     p1[0] = (unsigned char)(val >> 0);
115     p1[1] = (unsigned char)(val >> 8);
116     p1[2] = (unsigned char)(val >> 16);
117     p1[3] = (unsigned char)(val >> 24);
118 }
119 
120 __forceinline
121 void
122 WriteUnalignedU64(unsigned long long* p, unsigned long long val)
123 {
124     unsigned char* p1 = (unsigned char*)p;
125     p1[0] = (unsigned char)(val >> 0);
126     p1[1] = (unsigned char)(val >> 8);
127     p1[2] = (unsigned char)(val >> 16);
128     p1[3] = (unsigned char)(val >> 24);
129     p1[4] = (unsigned char)(val >> 32);
130     p1[5] = (unsigned char)(val >> 40);
131     p1[6] = (unsigned char)(val >> 48);
132     p1[7] = (unsigned char)(val >> 56);
133 }
134 
135 #endif // !UNALIGNED_ACCESS_ALLOWED
136 
137 #ifdef _WIN64
138 #define ReadUnalignedUlongPtr ReadUnalignedU64
139 #define WriteUnalignedUlongPtr WriteUnalignedU64
140 #else // _WIN64
141 #define ReadUnalignedUlongPtr ReadUnalignedU32
142 #define WriteUnalignedUlongPtr WriteUnalignedU32
143 #endif // _WIN64
144 
145 #ifdef __cplusplus
146 } // extern "C"
147 #endif
148