diff options
author | Aidan MacDonald <amachronic@protonmail.com> | 2022-06-26 17:19:40 +0100 |
---|---|---|
committer | Aidan MacDonald <amachronic@protonmail.com> | 2022-06-26 17:19:40 +0100 |
commit | ec9e484f64d120f9c0b70f4cc74b24dc83389acf (patch) | |
tree | 4dd6e85c8af66a66ca5a3e1a3ea2f6598f095fe0 /firmware/include/rbendian.h | |
parent | c3e75a1ce7b5eed965727eb1d69645d040aa35e8 (diff) | |
download | rockbox-ec9e484f64d120f9c0b70f4cc74b24dc83389acf.tar.gz rockbox-ec9e484f64d120f9c0b70f4cc74b24dc83389acf.zip |
firmware: Add load/store with endianness functions
Define common functions for loading 16/32/64-bit unsigned integers
with big, little, or host endianness, and distinguishing unaligned
and aligned cases.
Unaligned loads are supported generically by default, but this can
be overridden with a more efficient implementation on architectures
which support unaligned loads natively.
Change-Id: I3d826ec1a7646777876366eeece2cbccab60c1fb
Diffstat (limited to 'firmware/include/rbendian.h')
-rw-r--r-- | firmware/include/rbendian.h | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/firmware/include/rbendian.h b/firmware/include/rbendian.h index 8adcb544f9..8a6bb43a05 100644 --- a/firmware/include/rbendian.h +++ b/firmware/include/rbendian.h | |||
@@ -184,4 +184,241 @@ static inline uint32_t swaw32_hw(uint32_t value) | |||
184 | #error "Unknown endianness!" | 184 | #error "Unknown endianness!" |
185 | #endif | 185 | #endif |
186 | 186 | ||
187 | /* | ||
188 | * Generic unaligned loads | ||
189 | */ | ||
190 | static inline uint16_t _generic_load_le16(const void* p) | ||
191 | { | ||
192 | const uint8_t* d = p; | ||
193 | return d[0] | (d[1] << 8); | ||
194 | } | ||
195 | |||
196 | static inline uint32_t _generic_load_le32(const void* p) | ||
197 | { | ||
198 | const uint8_t* d = p; | ||
199 | return d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24); | ||
200 | } | ||
201 | |||
202 | static inline uint64_t _generic_load_le64(const void* p) | ||
203 | { | ||
204 | const uint8_t* d = p; | ||
205 | return (((uint64_t)d[0] << 0) | ((uint64_t)d[1] << 8) | | ||
206 | ((uint64_t)d[2] << 16) | ((uint64_t)d[3] << 24) | | ||
207 | ((uint64_t)d[4] << 32) | ((uint64_t)d[5] << 40) | | ||
208 | ((uint64_t)d[6] << 48) | ((uint64_t)d[7] << 56)); | ||
209 | } | ||
210 | |||
211 | static inline uint16_t _generic_load_be16(const void* p) | ||
212 | { | ||
213 | const uint8_t* d = p; | ||
214 | return (d[0] << 8) | d[1]; | ||
215 | } | ||
216 | |||
217 | static inline uint32_t _generic_load_be32(const void* p) | ||
218 | { | ||
219 | const uint8_t* d = p; | ||
220 | return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3]; | ||
221 | } | ||
222 | |||
223 | static inline uint64_t _generic_load_be64(const void* p) | ||
224 | { | ||
225 | const uint8_t* d = p; | ||
226 | return (((uint64_t)d[0] << 56) | ((uint64_t)d[1] << 48) | | ||
227 | ((uint64_t)d[2] << 40) | ((uint64_t)d[3] << 32) | | ||
228 | ((uint64_t)d[4] << 24) | ((uint64_t)d[5] << 16) | | ||
229 | ((uint64_t)d[6] << 8) | ((uint64_t)d[7] << 0)); | ||
230 | } | ||
231 | |||
232 | static inline void _generic_store_le16(void* p, uint16_t val) | ||
233 | { | ||
234 | uint8_t* d = p; | ||
235 | d[0] = val & 0xff; | ||
236 | d[1] = (val >> 8) & 0xff; | ||
237 | } | ||
238 | |||
239 | static inline void _generic_store_le32(void* p, uint32_t val) | ||
240 | { | ||
241 | uint8_t* d = p; | ||
242 | d[0] = val & 0xff; | ||
243 | d[1] = (val >> 8) & 0xff; | ||
244 | d[2] = (val >> 16) & 0xff; | ||
245 | d[3] = (val >> 24) & 0xff; | ||
246 | } | ||
247 | |||
248 | static inline void _generic_store_le64(void* p, uint64_t val) | ||
249 | { | ||
250 | uint8_t* d = p; | ||
251 | d[0] = val & 0xff; | ||
252 | d[1] = (val >> 8) & 0xff; | ||
253 | d[2] = (val >> 16) & 0xff; | ||
254 | d[3] = (val >> 24) & 0xff; | ||
255 | d[4] = (val >> 32) & 0xff; | ||
256 | d[5] = (val >> 40) & 0xff; | ||
257 | d[6] = (val >> 48) & 0xff; | ||
258 | d[7] = (val >> 56) & 0xff; | ||
259 | } | ||
260 | |||
261 | static inline void _generic_store_be16(void* p, uint16_t val) | ||
262 | { | ||
263 | uint8_t* d = p; | ||
264 | d[0] = (val >> 8) & 0xff; | ||
265 | d[1] = val & 0xff; | ||
266 | } | ||
267 | |||
268 | static inline void _generic_store_be32(void* p, uint32_t val) | ||
269 | { | ||
270 | uint8_t* d = p; | ||
271 | d[0] = (val >> 24) & 0xff; | ||
272 | d[1] = (val >> 16) & 0xff; | ||
273 | d[2] = (val >> 8) & 0xff; | ||
274 | d[3] = val & 0xff; | ||
275 | } | ||
276 | |||
277 | static inline void _generic_store_be64(void* p, uint64_t val) | ||
278 | { | ||
279 | uint8_t* d = p; | ||
280 | d[0] = (val >> 56) & 0xff; | ||
281 | d[1] = (val >> 48) & 0xff; | ||
282 | d[2] = (val >> 40) & 0xff; | ||
283 | d[3] = (val >> 32) & 0xff; | ||
284 | d[4] = (val >> 24) & 0xff; | ||
285 | d[5] = (val >> 16) & 0xff; | ||
286 | d[6] = (val >> 8) & 0xff; | ||
287 | d[7] = val & 0xff; | ||
288 | } | ||
289 | |||
290 | #if !defined(HAVE_UNALIGNED_LOAD_STORE) | ||
291 | |||
292 | /* Use generic unaligned loads */ | ||
293 | #define load_le16 _generic_load_le16 | ||
294 | #define load_le32 _generic_load_le32 | ||
295 | #define load_le64 _generic_load_le64 | ||
296 | #define load_be16 _generic_load_be16 | ||
297 | #define load_be32 _generic_load_be32 | ||
298 | #define load_be64 _generic_load_be64 | ||
299 | #define store_le16 _generic_store_le16 | ||
300 | #define store_le32 _generic_store_le32 | ||
301 | #define store_le64 _generic_store_le64 | ||
302 | #define store_be16 _generic_store_be16 | ||
303 | #define store_be32 _generic_store_be32 | ||
304 | #define store_be64 _generic_store_be64 | ||
305 | |||
306 | /* Define host byte order unaligned load */ | ||
307 | #if defined(ROCKBOX_LITTLE_ENDIAN) | ||
308 | # define load_h16 load_le16 | ||
309 | # define load_h32 load_le32 | ||
310 | # define load_h64 load_le64 | ||
311 | # define store_h16 store_le16 | ||
312 | # define store_h32 store_le32 | ||
313 | # define store_h64 store_le64 | ||
314 | #elif defined(ROCKBOX_BIG_ENDIAN) | ||
315 | # define load_h16 load_be16 | ||
316 | # define load_h32 load_be32 | ||
317 | # define load_h64 load_be64 | ||
318 | # define store_h16 store_be16 | ||
319 | # define store_h32 store_be32 | ||
320 | # define store_h64 store_be64 | ||
321 | #else | ||
322 | # error | ||
323 | #endif | ||
324 | |||
325 | #else /* HAVE_UNALIGNED_LOAD_STORE */ | ||
326 | |||
327 | /* The arch should define unaligned loads in host byte order */ | ||
328 | #if defined(ROCKBOX_LITTLE_ENDIAN) | ||
329 | # define load_le16 load_h16 | ||
330 | # define load_le32 load_h32 | ||
331 | # define load_le64 load_h64 | ||
332 | # define load_be16(p) swap16(load_h16((p))) | ||
333 | # define load_be32(p) swap32(load_h32((p))) | ||
334 | # define load_be64(p) swap64(load_h64((p))) | ||
335 | # define store_le16 store_h16 | ||
336 | # define store_le32 store_h32 | ||
337 | # define store_le64 store_h64 | ||
338 | # define store_be16(p,v) store_h16((p),swap16((v))) | ||
339 | # define store_be32(p,v) store_h32((p),swap32((v))) | ||
340 | # define store_be64(p,v) store_h64((p),swap64((v))) | ||
341 | #elif defined(ROCKBOX_BIG_ENDIAN) | ||
342 | # define load_le16(p) swap16(load_h16((p))) | ||
343 | # define load_le32(p) swap32(load_h32((p))) | ||
344 | # define load_le64(p) swap64(load_h64((p))) | ||
345 | # define load_be16 load_h16 | ||
346 | # define load_be32 load_h32 | ||
347 | # define load_be64 load_h64 | ||
348 | # define store_le16(p,v) store_h16((p),swap16((v))) | ||
349 | # define store_le32(p,v) store_h32((p),swap32((v))) | ||
350 | # define store_le64(p,v) store_h64((p),swap64((v))) | ||
351 | # define store_be16 store_h16 | ||
352 | # define store_be32 store_h32 | ||
353 | # define store_be64 store_h64 | ||
354 | #else | ||
355 | # error | ||
356 | #endif | ||
357 | |||
358 | #endif /* HAVE_UNALIGNED_LOAD_STORE */ | ||
359 | |||
360 | /* | ||
361 | * Aligned loads | ||
362 | */ | ||
363 | |||
364 | static inline uint16_t load_h16_aligned(const void* p) | ||
365 | { | ||
366 | return *(const uint16_t*)p; | ||
367 | } | ||
368 | |||
369 | static inline uint32_t load_h32_aligned(const void* p) | ||
370 | { | ||
371 | return *(const uint32_t*)p; | ||
372 | } | ||
373 | |||
374 | static inline uint64_t load_h64_aligned(const void* p) | ||
375 | { | ||
376 | return *(const uint64_t*)p; | ||
377 | } | ||
378 | |||
379 | static inline void store_h16_aligned(void* p, uint16_t val) | ||
380 | { | ||
381 | *(uint16_t*)p = val; | ||
382 | } | ||
383 | |||
384 | static inline void store_h32_aligned(void* p, uint32_t val) | ||
385 | { | ||
386 | *(uint32_t*)p = val; | ||
387 | } | ||
388 | |||
389 | static inline void store_h64_aligned(void* p, uint64_t val) | ||
390 | { | ||
391 | *(uint64_t*)p = val; | ||
392 | } | ||
393 | |||
394 | #if defined(ROCKBOX_LITTLE_ENDIAN) | ||
395 | # define load_le16_aligned load_h16_aligned | ||
396 | # define load_le32_aligned load_h32_aligned | ||
397 | # define load_le64_aligned load_h64_aligned | ||
398 | # define load_be16_aligned(p) swap16(load_h16_aligned((p))) | ||
399 | # define load_be32_aligned(p) swap32(load_h32_aligned((p))) | ||
400 | # define load_be64_aligned(p) swap64(load_h64_aligned((p))) | ||
401 | # define store_le16_aligned store_h16_aligned | ||
402 | # define store_le32_aligned store_h32_aligned | ||
403 | # define store_le64_aligned store_h64_aligned | ||
404 | # define store_be16_aligned(p,v) store_h16_aligned((p),swap16((v))) | ||
405 | # define store_be32_aligned(p,v) store_h32_aligned((p),swap32((v))) | ||
406 | # define store_be64_aligned(p,v) store_h64_aligned((p),swap64((v))) | ||
407 | #elif defined(ROCKBOX_BIG_ENDIAN) | ||
408 | # define load_le16_aligned(p) swap16(load_h16_aligned((p))) | ||
409 | # define load_le32_aligned(p) swap32(load_h32_aligned((p))) | ||
410 | # define load_le64_aligned(p) swap64(load_h64_aligned((p))) | ||
411 | # define load_be16_aligned load_h16_aligned | ||
412 | # define load_be32_aligned load_h32_aligned | ||
413 | # define load_be64_aligned load_h64_aligned | ||
414 | # define store_le16_aligned(p,v) store_h16_aligned((p),swap16((v))) | ||
415 | # define store_le32_aligned(p,v) store_h32_aligned((p),swap32((v))) | ||
416 | # define store_le64_aligned(p,v) store_h64_aligned((p),swap64((v))) | ||
417 | # define store_be16_aligned store_h16_aligned | ||
418 | # define store_be32_aligned store_h32_aligned | ||
419 | # define store_be64_aligned store_h64_aligned | ||
420 | #else | ||
421 | # error "Unknown endian!" | ||
422 | #endif | ||
423 | |||
187 | #endif /* _RBENDIAN_H_ */ | 424 | #endif /* _RBENDIAN_H_ */ |