1/* -*- linux-c -*- */
2/*
3 * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
10 */
11
12/****************************************************/
13/****************************************************/
14/*	    Begin header file "endian.h"	    */
15/****************************************************/
16/****************************************************/
17
18#if !defined(_ENDIAN_HP_)
19#define _ENDIAN_HP_
20
21/****************************************************/
22/*		    header files		    */
23/****************************************************/
24
25
26/****************************************************/
27/*  let's see if we know this is a big endian	    */
28/****************************************************/
29#ifndef INLINE
30#define INLINE inline
31#endif
32
33#define fnm_assert_stmt(a)
34
35#ifndef BYTE_ORDER
36#if defined(AMD29K) || defined(mc68000)
37
38#define BIG_ENDIAN     4321
39
40#endif
41
42/****************************************************/
43/*  global macro functions handling endian issues   */
44/****************************************************/
45
46#if !defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)
47#define LITTLE_ENDIAN 1234
48#endif
49#endif
50
51#define fnm_get_i_big_endian(p_uc, x)	    fnm_get_ui_big_endian(p_uc, x)
52#define fnm_get_s_big_endian(p_uc, x)	    fnm_get_us_big_endian(p_uc, x)
53#define fnm_get_i_little_endian(p_uc, x)    fnm_get_ui_little_endian(p_uc, x)
54#define fnm_get_s_little_endian(p_uc, x)    fnm_get_us_little_endian(p_uc, x)
55
56#define fnm_get_ui_big_endian(p_uc, x)					    \
57{									    \
58	(x) = (((unsigned int)(*(p_uc)++)) << 24);						\
59	(x) += (((unsigned int)(*(p_uc)++)) << 16);						\
60	(x) += (((unsigned int)(*(p_uc)++)) << 8);						\
61	(x) += ((unsigned int)(*(p_uc)++));							\
62}
63
64#define fnm_get_us_big_endian(p_uc, x)						\
65{										\
66	(x) = (((unsigned short)(*(p_uc)++)) << 8);						\
67	(x) += ((unsigned short)(*(p_uc)++));							\
68}
69
70#define fnm_get_ui_little_endian(p_uc, x)					\
71{										\
72	(x) = ((unsigned int)(*(p_uc)++));							\
73	(x) += (((unsigned int)(*(p_uc)++)) << 8);						\
74	(x) += (((unsigned int)(*(p_uc)++)) << 16);						\
75	(x) += (((unsigned int)(*(p_uc)++)) << 24);						\
76}
77
78#define fnm_get_us_little_endian(p_uc, x)					\
79{										\
80	(x) = ((unsigned short)(*(p_uc)++));							\
81	(x) += (((unsigned short)(*(p_uc)++)) << 8);						\
82}
83
84#define fnm_store_i_big_endian(p_uc, x)		fnm_store_ui_big_endian(p_uc, x)
85#define fnm_store_s_big_endian(p_uc, x)		fnm_store_us_big_endian(p_uc, x)
86#define fnm_store_i_little_endian(p_uc, x)  fnm_store_ui_little_endian(p_uc, x)
87#define fnm_store_s_little_endian(p_uc, x)  fnm_store_us_little_endian(p_uc, x)
88
89#define fnm_store_ui_big_endian(p_uc, x)					\
90{										\
91	*(p_uc)++ = (((unsigned int)(x)) >> 24);						\
92	*(p_uc)++ = (((unsigned int)(x)) >> 16);						\
93	*(p_uc)++ = (((unsigned int)(x)) >> 8);						\
94	*(p_uc)++ = ((unsigned int)(x));							\
95}
96
97#define fnm_store_us_big_endian(p_uc, x)					\
98{										\
99	*(p_uc)++ = (unsigned char) (((unsigned short)(x)) >> 8);				\
100	*(p_uc)++ = (unsigned char) ((unsigned short)(x));					\
101}
102
103#define fnm_store_ui_little_endian(p_uc, x)					\
104{										\
105	*(p_uc)++ = ((unsigned int)(x));							\
106	*(p_uc)++ = (((unsigned int)(x)) >> 8);						\
107	*(p_uc)++ = (((unsigned int)(x)) >> 16);						\
108	*(p_uc)++ = (((unsigned int)(x)) >> 24);						\
109}
110
111#define fnm_store_us_little_endian(p_uc, x)					\
112{										\
113	*(p_uc)++ = ((unsigned short)(x));							\
114	*(p_uc)++ = (((unsigned short)(x)) >> 8);						\
115}
116
117/* for now lets always use the macroes instead of the inline procedures
118   so that we are sure they work */
119
120
121#define fnm_convert_us_endian(x)						\
122	((unsigned short)((((unsigned short)(x)) << 8) + (((unsigned short)(x)) >> 8)))
123
124#define fnm_convert_ui_endian(x)						\
125	((unsigned int)((((unsigned int)(x)) >> 24) + ((((unsigned int)(x)) & 0x00ff0000) >> 8) +		\
126		 ((((unsigned int)(x)) & 0x0000ff00) << 8) + (((unsigned int)(x)) << 24)))
127
128#define fnm_make_ui_from_2_us(us_high_part, us_low_part)			\
129	((unsigned int)((((unsigned int)(us_high_part)) << 16) + ((unsigned short)(us_low_part))))
130
131#define fnm_make_ui_from_4_uc(p1, p2, p3, p4)					\
132	((unsigned int)(((((((unsigned int)((t_uc)p1) << 8) + ((t_uc)p2)) << 8)			\
133		+ ((t_uc)p3)) << 8) + ((t_uc)p4)))
134
135#define fnm_make_us_from_2_uc(uc_high_part, uc_low_part)			\
136	((unsigned short)((((unsigned short)(uc_high_part)) << 8) + ((t_uc)(uc_low_part))))
137
138
139#define fnm_convert_s_endian(x)		((short)(fnm_convert_us_endian(x)))
140#define fnm_convert_i_endian(x)		((int)(fnm_convert_ui_endian(x)))
141
142#if defined(BIG_ENDIAN)
143
144#define fnm_convert_us_big_endian(x)		((unsigned short)(x))
145#define fnm_convert_s_big_endian(x)		((short)(x))
146#define fnm_convert_ui_big_endian(x)		((unsigned int)(x))
147#define fnm_convert_i_big_endian(x)		((int)(x))
148
149#define fnm_convert_us_little_endian(x)		fnm_convert_us_endian(x)
150#define fnm_convert_s_little_endian(x)		fnm_convert_s_endian(x)
151#define fnm_convert_ui_little_endian(x)		fnm_convert_ui_endian(x)
152#define fnm_convert_i_little_endian(x)		fnm_convert_i_endian(x)
153
154#else
155
156#define fnm_convert_us_big_endian(x)		fnm_convert_us_endian(x)
157#define fnm_convert_s_big_endian(x)		fnm_convert_s_endian(x)
158#define fnm_convert_ui_big_endian(x)		fnm_convert_ui_endian(x)
159#define fnm_convert_i_big_endian(x)		fnm_convert_i_endian(x)
160
161#define fnm_convert_us_little_endian(x)		((unsigned short)(x))
162#define fnm_convert_s_little_endian(x)		((short)(x))
163#define fnm_convert_ui_little_endian(x)		((unsigned int)(x))
164#define fnm_convert_i_little_endian(x)		((int)(x))
165
166#endif
167
168/****************************************************/
169/*  test macro functions handling endian issues		*/
170/****************************************************/
171
172#if defined(NDEBUG)
173
174#define fnm_test_definitions()
175
176#else
177
178#define fnm_test_definitions()							\
179{										\
180	union									\
181	{										\
182	t_c	a_c[4];								\
183	unsigned short	a_us[2];							\
184	unsigned int	ul;								\
185										\
186	} t1 = { "\x01\x02\x03\x04" };						\
187										\
188	unsigned char	*p;									\
189	unsigned short	us_one, us_two;							\
190	unsigned int	ul_one;								\
191										\
192	fnm_assert_stmt((t1.a_c[0] == 1) && (t1.a_c[1] == 2) &&			\
193			(t1.a_c[2] == 3) && (t1.a_c[3] == 4));			\
194										\
195	fnm_assert_stmt(fnm_convert_ui_big_endian(t1.ul) == 0x01020304);		\
196	fnm_assert_stmt(fnm_convert_ui_little_endian(t1.ul) == 0x04030201);		\
197	fnm_assert_stmt(fnm_convert_us_big_endian(t1.a_us[0]) == 0x0102);		\
198	fnm_assert_stmt(fnm_convert_us_little_endian(t1.a_us[0]) == 0x0201);	\
199										\
200	p = (unsigned char*)(&t1);								\
201										\
202	fnm_get_us_little_endian(p, us_one);					\
203	fnm_get_us_little_endian(p, us_two);					\
204										\
205	fnm_assert_stmt((us_one == 0x0201) && (us_two == 0x0403));			\
206	fnm_assert_stmt((p-4) == ((unsigned char*)(&t1)));					\
207										\
208	p = (unsigned char*)(&t1);								\
209										\
210	fnm_get_us_big_endian(p, us_one);						\
211	fnm_get_us_big_endian(p, us_two);						\
212										\
213	fnm_assert_stmt((us_one == 0x0102) && (us_two == 0x0304));			\
214	fnm_assert_stmt((p-4) == ((unsigned char*)(&t1)));					\
215										\
216	p = (unsigned char*)(&t1);								\
217										\
218	fnm_get_ui_little_endian(p, ul_one);					\
219										\
220	fnm_assert_stmt(ul_one == 0x04030201);					\
221	fnm_assert_stmt((p-4) == ((unsigned char*)(&t1)));					\
222										\
223	p = (unsigned char*)(&t1);								\
224										\
225	fnm_get_ui_big_endian(p, ul_one);						\
226										\
227	fnm_assert_stmt(ul_one == 0x01020304);					\
228	fnm_assert_stmt((p-4) == ((unsigned char*)(&t1)));					\
229										\
230	p = (unsigned char*)(&t1);								\
231										\
232	fnm_store_us_little_endian(p, 0x1234);					\
233	fnm_store_us_little_endian(p, 0x5678);					\
234	fnm_assert_stmt((p-4) == ((unsigned char*)(&t1)));					\
235										\
236	p = (unsigned char*)(&t1);								\
237										\
238	fnm_get_us_little_endian(p, us_one);					\
239	fnm_get_us_little_endian(p, us_two);					\
240										\
241	fnm_assert_stmt((us_one == 0x1234) && (us_two == 0x5678));			\
242	fnm_assert_stmt((p-4) == ((unsigned char*)(&t1)));					\
243										\
244	p = (unsigned char*)(&t1);								\
245										\
246	fnm_store_us_big_endian(p, 0x1234);						\
247	fnm_store_us_big_endian(p, 0x5678);						\
248	fnm_assert_stmt((p-4) == ((unsigned char*)(&t1)));					\
249										\
250	p = (unsigned char*)(&t1);								\
251										\
252	fnm_get_us_big_endian(p, us_one);						\
253	fnm_get_us_big_endian(p, us_two);						\
254										\
255	fnm_assert_stmt((us_one == 0x1234) && (us_two == 0x5678));			\
256	fnm_assert_stmt((p-4) == ((unsigned char*)(&t1)));					\
257										\
258	p = (unsigned char*)(&t1);								\
259										\
260	fnm_store_ui_little_endian(p, 0x12345678);					\
261	fnm_assert_stmt((p-4) == ((unsigned char*)(&t1)));					\
262										\
263	p = (unsigned char*)(&t1);								\
264										\
265	fnm_get_ui_little_endian(p, ul_one);					\
266										\
267	fnm_assert_stmt(ul_one == 0x12345678);					\
268	fnm_assert_stmt((p-4) == ((unsigned char*)(&t1)));					\
269										\
270	p = (unsigned char*)(&t1);								\
271										\
272	fnm_store_ui_big_endian(p, 0x12345678);					\
273	fnm_assert_stmt((p-4) == ((unsigned char*)(&t1)));					\
274										\
275	p = (unsigned char*)(&t1);								\
276										\
277	fnm_get_ui_big_endian(p, ul_one);						\
278										\
279	fnm_assert_stmt(ul_one == 0x12345678);					\
280	fnm_assert_stmt((p-4) == ((unsigned char*)(&t1)));					\
281										\
282	fnm_assert_stmt(fnm_make_ui_from_2_us(1, 2) == 0x00010002);			\
283	fnm_assert_stmt(fnm_make_ui_from_4_uc(1, 2, 3, 4) == 0x01020304);		\
284	fnm_assert_stmt(fnm_make_us_from_2_uc(1, 2) == 0x0102);			\
285										\
286}
287
288#endif
289
290#endif
291
292/****************************************************/
293/****************************************************/
294/*		End header file "endian.h"			*/
295/****************************************************/
296/****************************************************/
297