1 /* 2 * gauche/bytesP.h - Some speed-sensitive byte-swapping routines 3 * 4 * Copyright (c) 2009-2020 Shiro Kawai <shiro@acm.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the authors nor the names of its contributors 18 * may be used to endorse or promote products derived from this 19 * software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 27 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #ifndef GAUCHE_PRIV_BYTESP_H 35 #define GAUCHE_PRIV_BYTESP_H 36 37 #include "gauche/priv/builtin-syms.h" 38 39 /* Gauche use big-endian / little-endian. scheme.bytevector requires 40 big / little. We recognize both. */ 41 #define SCM_IS_BE(endian) \ 42 (SCM_EQ(SCM_OBJ(endian), SCM_SYM_BIG_ENDIAN) \ 43 || (SCM_EQ(SCM_OBJ(endian), SCM_SYM_BIG))) 44 #define SCM_IS_LE(endian) \ 45 (SCM_EQ(SCM_OBJ(endian), SCM_SYM_LITTLE_ENDIAN) \ 46 || SCM_EQ(SCM_OBJ(endian), SCM_SYM_LITTLE)) 47 #define SCM_IS_ARM_LE(endian) \ 48 (SCM_EQ(SCM_OBJ(endian), SCM_SYM_ARM_LITTLE_ENDIAN)) 49 50 #if WORDS_BIGENDIAN 51 #define SWAP_REQUIRED(endian) (!SCM_IS_BE(endian)) 52 #else /*!WORDS_BIGENDIAN. Covers both little-endian and arm-little-endian. */ 53 #define SWAP_REQUIRED(endian) SCM_IS_BE(endian) 54 #endif 55 56 57 /* 58 * Swapping macros. They can be used both ways (native <-> external) 59 */ 60 61 typedef union { char buf[2]; int16_t val; } swap_s16_t; 62 typedef union { char buf[2]; uint16_t val; } swap_u16_t; 63 typedef union { char buf[4]; int32_t val; } swap_s32_t; 64 typedef union { char buf[4]; uint32_t val; } swap_u32_t; 65 typedef union { char buf[8]; int64_t val; } swap_s64_t; 66 typedef union { char buf[8]; uint64_t val; } swap_u64_t; 67 68 typedef union { char buf[2]; ScmHalfFloat val; } swap_f16_t; 69 typedef union { char buf[4]; float val; } swap_f32_t; 70 typedef union { char buf[8]; double val; } swap_f64_t; 71 72 #define CSWAP(buf, tmp, n, m) (tmp=buf[n], buf[n]=buf[m], buf[m]=tmp) 73 74 /* In the following macros, 'v' is of type one of the suitable swap_*_t. */ 75 76 #define SWAP_2(v) \ 77 do { char tmp; CSWAP(v.buf, tmp, 0, 1); } while (0) 78 79 #define SWAP_4(v) \ 80 do { char tmp; \ 81 CSWAP(v.buf, tmp, 0, 3); CSWAP(v.buf, tmp, 1, 2); \ 82 } while (0) 83 84 #define SWAP_8(v) \ 85 do { char tmp; \ 86 CSWAP(v.buf, tmp, 0, 7); CSWAP(v.buf, tmp, 1, 6); \ 87 CSWAP(v.buf, tmp, 2, 5); CSWAP(v.buf, tmp, 3, 4); \ 88 } while (0) 89 90 /* Swapping for double float is a bit tricky for ARM_LE case: 91 BE<->ARM : [01234567] -> [32107654] 92 LE<->ARM : [01234567] -> [45670123] 93 */ 94 #define SWAP_ARM2BE(v) \ 95 do { char tmp; \ 96 CSWAP(v.buf, tmp, 0, 3); CSWAP(v.buf, tmp, 1, 2); \ 97 CSWAP(v.buf, tmp, 4, 7); CSWAP(v.buf, tmp, 5, 6); \ 98 } while (0) 99 100 #define SWAP_ARM2LE(v) \ 101 do { char tmp; \ 102 CSWAP(v.buf, tmp, 0, 4); CSWAP(v.buf, tmp, 1, 5); \ 103 CSWAP(v.buf, tmp, 2, 6); CSWAP(v.buf, tmp, 3, 7); \ 104 } while (0) 105 106 107 #endif /*GAUCHE_PRIV_BYTESP_H*/ 108