diff options
Diffstat (limited to 'src/unaligned.h')
| -rw-r--r-- | src/unaligned.h | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/unaligned.h b/src/unaligned.h new file mode 100644 index 00000000..524b35c8 --- /dev/null +++ b/src/unaligned.h @@ -0,0 +1,98 @@ +/* Unaligned memory access functionality. + Copyright (C) 2000, 2001, 2002, 2003 Red Hat, Inc. + Written by Ulrich Drepper <[email protected]>, 2001. + + This program is Open Source software; you can redistribute it and/or + modify it under the terms of the Open Software License version 1.0 as + published by the Open Source Initiative. + + You should have received a copy of the Open Software License along + with this program; if not, you may obtain a copy of the Open Software + License version 1.0 from http://www.opensource.org/licenses/osl.php or + by writing the Open Source Initiative c/o Lawrence Rosen, Esq., + 3001 King Ranch Road, Ukiah, CA 95482. */ + +#ifndef _UNALIGNED_H +#define _UNALIGNED_H 1 + +#include <byteswap.h> +#include <endian.h> + + +#ifndef UNALIGNED_ACCESS_CLASS +# error "UNALIGNED_ACCESS_CLASS must be defined" +#endif + + +/* Macros to convert from the host byte order to that of the object file. */ +#if UNALIGNED_ACCESS_CLASS == BYTE_ORDER +# define target_bswap_16(n) (n) +# define target_bswap_32(n) (n) +# define target_bswap_64(n) (n) +#else +# define target_bswap_16(n) bswap_16 (n) +# define target_bswap_32(n) bswap_32 (n) +# define target_bswap_64(n) bswap_64 (n) +#endif + + +union u_2ubyte_unaligned +{ + uint16_t u; + char c[2]; +} __attribute__((packed)); + +union u_4ubyte_unaligned +{ + uint32_t u; + char c[4]; +} __attribute__((packed)); + +union u_8ubyte_unaligned +{ + uint64_t u; + char c[8]; +} __attribute__((packed)); + + +/* Macros to store value at unaligned address. */ +#define store_2ubyte_unaligned(ptr, value) \ + (void) (((union u_2ubyte_unaligned *) (ptr))->u = target_bswap_16 (value)) +#define store_4ubyte_unaligned(ptr, value) \ + (void) (((union u_4ubyte_unaligned *) (ptr))->u = target_bswap_32 (value)) +#define store_8ubyte_unaligned(ptr, value) \ + (void) (((union u_8ubyte_unaligned *) (ptr))->u = target_bswap_64 (value)) + + +/* Macros to add value to unaligned address. This is a bit more + complicated since the value must be read from memory and eventually + converted twice. */ +#if UNALIGNED_ACCESS_CLASS == BYTE_ORDER +# define add_2ubyte_unaligned(ptr, value) \ + (void) (((union u_2ubyte_unaligned *) (ptr))->u += value) +# define add_4ubyte_unaligned(ptr, value) \ + (void) (((union u_4ubyte_unaligned *) (ptr))->u += value) +# define add_8ubyte_unaligned(ptr, value) \ + (void) (((union u_8ubyte_unaligned *) (ptr))->u += value) +#else +# define add_2ubyte_unaligned(ptr, value) \ + do { \ + union u_2ubyte_unaligned *_ptr = (ptr); \ + uint16_t _val = bswap_16 (_ptr->u) + (value); \ + _ptr->u = bswap_16 (_val); \ + } while (0) +# define add_4ubyte_unaligned(ptr, value) \ + do { \ + union u_4ubyte_unaligned *_ptr = (ptr); \ + uint32_t _val = bswap_32 (_ptr->u) + (value); \ + _ptr->u = bswap_32 (_val); \ + } while (0) +# define add_8ubyte_unaligned(ptr, value) \ + do { \ + union u_8ubyte_unaligned *_ptr = (ptr); \ + uint64_t _val = bswap_64 (_ptr->u) + (value); \ + _ptr->u = bswap_64 (_val); \ + } while (0) +#endif + +#endif /* unaligned.h */ |
