1 /*
2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #define VPX_INLINE __inline
12 
13 #ifndef VPX_VPX_PORTS_MEM_OPS_H_
14 #define VPX_VPX_PORTS_MEM_OPS_H_
15 
16 /* \file
17  * \brief Provides portable memory access primitives
18  *
19  * This function provides portable primitives for getting and setting of
20  * signed and unsigned integers in 16, 24, and 32 bit sizes. The operations
21  * can be performed on unaligned data regardless of hardware support for
22  * unaligned accesses.
23  *
24  * The type used to pass the integral values may be changed by defining
25  * MEM_VALUE_T with the appropriate type. The type given must be an integral
26  * numeric type.
27  *
28  * The actual functions instantiated have the MEM_VALUE_T type name pasted
29  * on to the symbol name. This allows the developer to instantiate these
30  * operations for multiple types within the same translation unit. This is
31  * of somewhat questionable utility, but the capability exists nonetheless.
32  * Users not making use of this functionality should call the functions
33  * without the type name appended, and the preprocessor will take care of
34  * it.
35  *
36  * NOTE: This code is not supported on platforms where char > 1 octet ATM.
37  */
38 
39 #ifndef MAU_T
40 /* Minimum Access Unit for this target */
41 #define MAU_T unsigned char
42 #endif
43 
44 #ifndef MEM_VALUE_T
45 #define MEM_VALUE_T int
46 #endif
47 
48 #undef MEM_VALUE_T_SZ_BITS
49 #define MEM_VALUE_T_SZ_BITS (sizeof(MEM_VALUE_T) << 3)
50 
51 #undef mem_ops_wrap_symbol
52 #define mem_ops_wrap_symbol(fn) mem_ops_wrap_symbol2(fn, MEM_VALUE_T)
53 #undef mem_ops_wrap_symbol2
54 #define mem_ops_wrap_symbol2(fn, typ) mem_ops_wrap_symbol3(fn, typ)
55 #undef mem_ops_wrap_symbol3
56 #define mem_ops_wrap_symbol3(fn, typ) fn##_as_##typ
57 
58 /*
59  * Include aligned access routines
60  */
61 #define INCLUDED_BY_MEM_OPS_H
62 #include "mem_ops_aligned.h"
63 #undef INCLUDED_BY_MEM_OPS_H
64 
65 #undef mem_get_be16
66 #define mem_get_be16 mem_ops_wrap_symbol(mem_get_be16)
mem_get_be16(const void * vmem)67 static unsigned MEM_VALUE_T mem_get_be16(const void *vmem) {
68   unsigned MEM_VALUE_T val;
69   const MAU_T *mem = (const MAU_T *)vmem;
70 
71   val = mem[0] << 8;
72   val |= (unsigned)mem[1];
73   return val;
74 }
75 
76 #undef mem_get_be24
77 #define mem_get_be24 mem_ops_wrap_symbol(mem_get_be24)
mem_get_be24(const void * vmem)78 static unsigned MEM_VALUE_T mem_get_be24(const void *vmem) {
79   unsigned MEM_VALUE_T val;
80   const MAU_T *mem = (const MAU_T *)vmem;
81 
82   val = mem[0] << 16;
83   val |= mem[1] << 8;
84   val |= (unsigned)mem[2];
85   return val;
86 }
87 
88 #undef mem_get_be32
89 #define mem_get_be32 mem_ops_wrap_symbol(mem_get_be32)
mem_get_be32(const void * vmem)90 static unsigned MEM_VALUE_T mem_get_be32(const void *vmem) {
91   unsigned MEM_VALUE_T val;
92   const MAU_T *mem = (const MAU_T *)vmem;
93 
94   val = ((unsigned MEM_VALUE_T)mem[0]) << 24;
95   val |= mem[1] << 16;
96   val |= mem[2] << 8;
97   val |= (unsigned)mem[3];
98   return val;
99 }
100 
101 #undef mem_get_le16
102 #define mem_get_le16 mem_ops_wrap_symbol(mem_get_le16)
mem_get_le16(const void * vmem)103 static unsigned MEM_VALUE_T mem_get_le16(const void *vmem) {
104   unsigned MEM_VALUE_T val;
105   const MAU_T *mem = (const MAU_T *)vmem;
106 
107   val = mem[1] << 8;
108   val |= (unsigned)mem[0];
109   return val;
110 }
111 
112 #undef mem_get_le24
113 #define mem_get_le24 mem_ops_wrap_symbol(mem_get_le24)
mem_get_le24(const void * vmem)114 static unsigned MEM_VALUE_T mem_get_le24(const void *vmem) {
115   unsigned MEM_VALUE_T val;
116   const MAU_T *mem = (const MAU_T *)vmem;
117 
118   val = mem[2] << 16;
119   val |= mem[1] << 8;
120   val |= (unsigned)mem[0];
121   return val;
122 }
123 
124 #undef mem_get_le32
125 #define mem_get_le32 mem_ops_wrap_symbol(mem_get_le32)
mem_get_le32(const void * vmem)126 static unsigned MEM_VALUE_T mem_get_le32(const void *vmem) {
127   unsigned MEM_VALUE_T val;
128   const MAU_T *mem = (const MAU_T *)vmem;
129 
130   val = ((unsigned MEM_VALUE_T)mem[3]) << 24;
131   val |= mem[2] << 16;
132   val |= mem[1] << 8;
133   val |= (unsigned)mem[0];
134   return val;
135 }
136 
137 #define mem_get_s_generic(end, sz)                                            \
138   static VPX_INLINE signed MEM_VALUE_T mem_get_s##end##sz(const void *vmem) { \
139     const MAU_T *mem = (const MAU_T *)vmem;                                   \
140     signed MEM_VALUE_T val = mem_get_##end##sz(mem);                          \
141     return (val << (MEM_VALUE_T_SZ_BITS - sz)) >> (MEM_VALUE_T_SZ_BITS - sz); \
142   }
143 
144 /* clang-format off */
145 #undef  mem_get_sbe16
146 #define mem_get_sbe16 mem_ops_wrap_symbol(mem_get_sbe16)
147 mem_get_s_generic(be, 16)
148 
149 #undef  mem_get_sbe24
150 #define mem_get_sbe24 mem_ops_wrap_symbol(mem_get_sbe24)
151 mem_get_s_generic(be, 24)
152 
153 #undef  mem_get_sbe32
154 #define mem_get_sbe32 mem_ops_wrap_symbol(mem_get_sbe32)
155 mem_get_s_generic(be, 32)
156 
157 #undef  mem_get_sle16
158 #define mem_get_sle16 mem_ops_wrap_symbol(mem_get_sle16)
159 mem_get_s_generic(le, 16)
160 
161 #undef  mem_get_sle24
162 #define mem_get_sle24 mem_ops_wrap_symbol(mem_get_sle24)
163 mem_get_s_generic(le, 24)
164 
165 #undef  mem_get_sle32
166 #define mem_get_sle32 mem_ops_wrap_symbol(mem_get_sle32)
167 mem_get_s_generic(le, 32)
168 
169 #undef  mem_put_be16
170 #define mem_put_be16 mem_ops_wrap_symbol(mem_put_be16)
mem_put_be16(void * vmem,MEM_VALUE_T val)171 static VPX_INLINE void mem_put_be16(void *vmem, MEM_VALUE_T val) {
172   MAU_T *mem = (MAU_T *)vmem;
173 
174   mem[0] = (MAU_T)((val >> 8) & 0xff);
175   mem[1] = (MAU_T)((val >> 0) & 0xff);
176 }
177 
178 #undef  mem_put_be24
179 #define mem_put_be24 mem_ops_wrap_symbol(mem_put_be24)
mem_put_be24(void * vmem,MEM_VALUE_T val)180 static VPX_INLINE void mem_put_be24(void *vmem, MEM_VALUE_T val) {
181   MAU_T *mem = (MAU_T *)vmem;
182 
183   mem[0] = (MAU_T)((val >> 16) & 0xff);
184   mem[1] = (MAU_T)((val >>  8) & 0xff);
185   mem[2] = (MAU_T)((val >>  0) & 0xff);
186 }
187 
188 #undef  mem_put_be32
189 #define mem_put_be32 mem_ops_wrap_symbol(mem_put_be32)
mem_put_be32(void * vmem,MEM_VALUE_T val)190 static VPX_INLINE void mem_put_be32(void *vmem, MEM_VALUE_T val) {
191   MAU_T *mem = (MAU_T *)vmem;
192 
193   mem[0] = (MAU_T)((val >> 24) & 0xff);
194   mem[1] = (MAU_T)((val >> 16) & 0xff);
195   mem[2] = (MAU_T)((val >>  8) & 0xff);
196   mem[3] = (MAU_T)((val >>  0) & 0xff);
197 }
198 
199 #undef  mem_put_le16
200 #define mem_put_le16 mem_ops_wrap_symbol(mem_put_le16)
mem_put_le16(void * vmem,MEM_VALUE_T val)201 static VPX_INLINE void mem_put_le16(void *vmem, MEM_VALUE_T val) {
202   MAU_T *mem = (MAU_T *)vmem;
203 
204   mem[0] = (MAU_T)((val >> 0) & 0xff);
205   mem[1] = (MAU_T)((val >> 8) & 0xff);
206 }
207 
208 #undef  mem_put_le24
209 #define mem_put_le24 mem_ops_wrap_symbol(mem_put_le24)
mem_put_le24(void * vmem,MEM_VALUE_T val)210 static VPX_INLINE void mem_put_le24(void *vmem, MEM_VALUE_T val) {
211   MAU_T *mem = (MAU_T *)vmem;
212 
213   mem[0] = (MAU_T)((val >>  0) & 0xff);
214   mem[1] = (MAU_T)((val >>  8) & 0xff);
215   mem[2] = (MAU_T)((val >> 16) & 0xff);
216 }
217 
218 #undef  mem_put_le32
219 #define mem_put_le32 mem_ops_wrap_symbol(mem_put_le32)
mem_put_le32(void * vmem,MEM_VALUE_T val)220 static VPX_INLINE void mem_put_le32(void *vmem, MEM_VALUE_T val) {
221   MAU_T *mem = (MAU_T *)vmem;
222 
223   mem[0] = (MAU_T)((val >>  0) & 0xff);
224   mem[1] = (MAU_T)((val >>  8) & 0xff);
225   mem[2] = (MAU_T)((val >> 16) & 0xff);
226   mem[3] = (MAU_T)((val >> 24) & 0xff);
227 }
228 /* clang-format on */
229 
230 #endif  // VPX_VPX_PORTS_MEM_OPS_H_
231