xref: /netbsd-src/sys/arch/arm/include/byte_swap.h (revision b31d312c1534c49250479a70f29ce544cc34e438)
1*b31d312cSrin /*	$NetBSD: byte_swap.h,v 1.16 2017/01/17 11:08:50 rin Exp $	*/
2da5ef20bSthorpej 
3da5ef20bSthorpej /*-
4da5ef20bSthorpej  * Copyright (c) 1997, 1999, 2002 The NetBSD Foundation, Inc.
5da5ef20bSthorpej  * All rights reserved.
6da5ef20bSthorpej  *
7da5ef20bSthorpej  * This code is derived from software contributed to The NetBSD Foundation
8da5ef20bSthorpej  * by Charles M. Hannum, Neil A. Carson, and Jason R. Thorpe.
9da5ef20bSthorpej  *
10da5ef20bSthorpej  * Redistribution and use in source and binary forms, with or without
11da5ef20bSthorpej  * modification, are permitted provided that the following conditions
12da5ef20bSthorpej  * are met:
13da5ef20bSthorpej  * 1. Redistributions of source code must retain the above copyright
14da5ef20bSthorpej  *    notice, this list of conditions and the following disclaimer.
15da5ef20bSthorpej  * 2. Redistributions in binary form must reproduce the above copyright
16da5ef20bSthorpej  *    notice, this list of conditions and the following disclaimer in the
17da5ef20bSthorpej  *    documentation and/or other materials provided with the distribution.
18da5ef20bSthorpej  *
19da5ef20bSthorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20da5ef20bSthorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21da5ef20bSthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22da5ef20bSthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23da5ef20bSthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24da5ef20bSthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25da5ef20bSthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26da5ef20bSthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27da5ef20bSthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28da5ef20bSthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29da5ef20bSthorpej  * POSSIBILITY OF SUCH DAMAGE.
30da5ef20bSthorpej  */
31da5ef20bSthorpej 
32da5ef20bSthorpej #ifndef _ARM_BYTE_SWAP_H_
33da5ef20bSthorpej #define	_ARM_BYTE_SWAP_H_
34da5ef20bSthorpej 
3567e5bbcbSmatt #ifdef _LOCORE
3667e5bbcbSmatt 
374777b0bfSmatt #if defined(_ARM_ARCH_6) || defined(_ARM_ARCH_7)
3867e5bbcbSmatt 
3967e5bbcbSmatt #define	BSWAP16(_src, _dst, _tmp)		\
4067e5bbcbSmatt 	rev16	_dst, _src
4167e5bbcbSmatt #define	BSWAP32(_src, _dst, _tmp)		\
4267e5bbcbSmatt 	rev	_dst, _src
4367e5bbcbSmatt 
4467e5bbcbSmatt #else
4567e5bbcbSmatt 
4667e5bbcbSmatt #define	BSWAP16(_src, _dst, _tmp)		\
4767e5bbcbSmatt 	mov	_tmp, _src, ror #8		;\
4867e5bbcbSmatt 	orr	_tmp, _tmp, _tmp, lsr #16	;\
4967e5bbcbSmatt 	bic	_dst, _tmp, _tmp, lsl #16
5067e5bbcbSmatt 
5167e5bbcbSmatt #define	BSWAP32(_src, _dst, _tmp)		\
5267e5bbcbSmatt 	eor	_tmp, _src, _src, ror #16	;\
5367e5bbcbSmatt 	bic	_tmp, _tmp, #0x00FF0000		;\
5467e5bbcbSmatt 	mov	_dst, _src, ror #8		;\
5567e5bbcbSmatt 	eor	_dst, _dst, _tmp, lsr #8
5667e5bbcbSmatt 
5767e5bbcbSmatt #endif
5867e5bbcbSmatt 
5967e5bbcbSmatt 
6067e5bbcbSmatt #else
6167e5bbcbSmatt 
62c88ae1f9Sdsl #ifdef __GNUC__
63da5ef20bSthorpej #include <sys/types.h>
64c88ae1f9Sdsl __BEGIN_DECLS
65da5ef20bSthorpej 
66c88ae1f9Sdsl #define	__BYTE_SWAP_U32_VARIABLE __byte_swap_u32_variable
67c88ae1f9Sdsl static __inline uint32_t
__byte_swap_u32_variable(uint32_t v)68c88ae1f9Sdsl __byte_swap_u32_variable(uint32_t v)
69da5ef20bSthorpej {
70c88ae1f9Sdsl 	uint32_t t1;
71da5ef20bSthorpej 
72dd02d63dSmatt #ifdef _ARM_ARCH_6
73dd02d63dSmatt 	if (!__builtin_constant_p(v)) {
74dd02d63dSmatt 		__asm("rev\t%0, %1" : "=r" (v) : "0" (v));
75dd02d63dSmatt 		return v;
76dd02d63dSmatt 	}
77dd02d63dSmatt #endif
78dd02d63dSmatt 
79201e41fcSthorpej 	t1 = v ^ ((v << 16) | (v >> 16));
80c05e648eSthorpej 	t1 &= 0xff00ffffU;
81201e41fcSthorpej 	v = (v >> 8) | (v << 24);
82201e41fcSthorpej 	v ^= (t1 >> 8);
83dd02d63dSmatt 
84*b31d312cSrin 	return v;
85da5ef20bSthorpej }
86da5ef20bSthorpej 
87c88ae1f9Sdsl #define	__BYTE_SWAP_U16_VARIABLE __byte_swap_u16_variable
88c88ae1f9Sdsl static __inline uint16_t
__byte_swap_u16_variable(uint16_t v)89c88ae1f9Sdsl __byte_swap_u16_variable(uint16_t v)
90da5ef20bSthorpej {
91da5ef20bSthorpej 
92825088edSmatt #ifdef _ARM_ARCH_6
93dd02d63dSmatt 	if (!__builtin_constant_p(v)) {
94674f7f26Smatt 		uint32_t v32 = v;
95674f7f26Smatt 		__asm("rev16\t%0, %1" : "=r" (v32) : "0" (v32));
961ed40762Smartin 		return (uint16_t)v32;
97dd02d63dSmatt 	}
98e500dd53Smatt #elif !defined(__thumb__) && 0	/* gcc produces decent code for this */
99dd02d63dSmatt 	if (!__builtin_constant_p(v)) {
100e500dd53Smatt 		uint32_t v0 = v;
1015f1c88d7Sperry 		__asm volatile(
102da5ef20bSthorpej 			"mov	%0, %1, ror #8\n"
103da5ef20bSthorpej 			"orr	%0, %0, %0, lsr #16\n"
104da5ef20bSthorpej 			"bic	%0, %0, %0, lsl #16"
105e500dd53Smatt 		: "=&r" (v0)
106e500dd53Smatt 		: "0" (v0));
1071ed40762Smartin 		return (uint16_t)v0;
108dd02d63dSmatt 	}
109dd02d63dSmatt #endif
110825088edSmatt 	v &= 0xffff;
111ddcad3a9Schristos 	v = (uint16_t)((v >> 8) | (v << 8));
112da5ef20bSthorpej 
113*b31d312cSrin 	return v;
114da5ef20bSthorpej }
115da5ef20bSthorpej 
116c88ae1f9Sdsl __END_DECLS
117c88ae1f9Sdsl #endif
118da5ef20bSthorpej 
11967e5bbcbSmatt #endif	/* _LOCORE */
120da5ef20bSthorpej 
121da5ef20bSthorpej #endif /* _ARM_BYTE_SWAP_H_ */
122