libsidplayfp  0.3.5
sidendian.h
1 /***************************************************************************
2  sidendian.h - Improtant endian functions
3  -------------------
4  begin : Mon Jul 3 2000
5  copyright : (C) 2000 by Simon White
6  email : s_a_white@email.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 /***************************************************************************
18  * $Log: sidendian.h,v $
19  * Revision 1.6 2005/11/20 11:02:06 s_a_white
20  * Work around for bug in gcc 4 (optimiser breaks if variable never has a
21  * direct assignment).
22  *
23  * Revision 1.5 2001/07/03 22:44:13 s_a_white
24  * Added endian_16 to convert a 16 bit value to an array of 8s.
25  *
26  * Revision 1.4 2001/05/07 16:27:24 s_a_white
27  * Fix optimisation issues with gcc 2.96.
28  *
29  * Revision 1.3 2001/03/25 19:46:12 s_a_white
30  * _endian_h_ changed to _sidendian_h_.
31  *
32  * Revision 1.2 2001/03/10 19:49:32 s_a_white
33  * Removed bad include.
34  *
35  * Revision 1.1 2001/03/02 19:04:38 s_a_white
36  * Include structure modified for better compatibility
37  *
38  * Revision 1.5 2001/01/07 16:01:33 s_a_white
39  * sidendian.h is now installed, therefore endian defines updated.
40  *
41  * Revision 1.4 2000/12/13 17:53:01 s_a_white
42  * Fixes some of the endian calls.
43  *
44  * Revision 1.3 2000/12/12 19:39:15 s_a_white
45  * Removed bad const.
46  *
47  * Revision 1.2 2000/12/11 19:10:59 s_a_white
48  * AC99 Update.
49  *
50  ***************************************************************************/
51 
52 #ifndef _sidendian_h_
53 #define _sidendian_h_
54 
55 // NOTE: The optimisations in this file rely on the structure of memory
56 // e.g. 2 shorts being contained in 1 long. Although these sizes are
57 // checked to make sure the optimisation is ok, gcc 2.96 (and above)
58 // introduced better optimisations. This results in caching of values
59 // in internal registers and therefore writes to ram through the aliases
60 // not being reflected in the CPU regs. The use of the volatile keyword
61 // fixes this.
62 
63 #include "sidtypes.h"
64 
65 /*
66 Labeling:
67 0 - LO
68 1 - HI
69 2 - HILO
70 3 - HIHI
71 */
72 
74 // INT16 FUNCTIONS
76 // Set the lo byte (8 bit) in a word (16 bit)
77 inline void endian_16lo8 (uint_least16_t &word, uint8_t byte)
78 {
79  word &= 0xff00;
80  word |= byte;
81 }
82 
83 // Get the lo byte (8 bit) in a word (16 bit)
84 inline uint8_t endian_16lo8 (uint_least16_t word)
85 {
86  return (uint8_t) word;
87 }
88 
89 // Set the hi byte (8 bit) in a word (16 bit)
90 inline void endian_16hi8 (uint_least16_t &word, uint8_t byte)
91 {
92  word &= 0x00ff;
93  word |= (uint_least16_t) byte << 8;
94 }
95 
96 // Set the hi byte (8 bit) in a word (16 bit)
97 inline uint8_t endian_16hi8 (uint_least16_t word)
98 {
99  return (uint8_t) (word >> 8);
100 }
101 
102 // Swap word endian.
103 inline void endian_16swap8 (uint_least16_t &word)
104 {
105  uint8_t lo = endian_16lo8 (word);
106  uint8_t hi = endian_16hi8 (word);
107  endian_16lo8 (word, hi);
108  endian_16hi8 (word, lo);
109 }
110 
111 // Convert high-byte and low-byte to 16-bit word.
112 inline uint_least16_t endian_16 (uint8_t hi, uint8_t lo)
113 {
114  uint_least16_t word = 0;
115  endian_16lo8 (word, lo);
116  endian_16hi8 (word, hi);
117  return word;
118 }
119 
120 // Convert high-byte and low-byte to 16-bit little endian word.
121 inline void endian_16 (uint8_t ptr[2], uint_least16_t word)
122 {
123 # if defined(WORDS_BIGENDIAN)
124  ptr[0] = endian_16hi8 (word);
125  ptr[1] = endian_16lo8 (word);
126 # else
127  ptr[0] = endian_16lo8 (word);
128  ptr[1] = endian_16hi8 (word);
129 # endif
130 }
131 
132 inline void endian_16 (char ptr[2], uint_least16_t word)
133 {
134  endian_16 ((uint8_t *) ptr, word);
135 }
136 
137 // Convert high-byte and low-byte to 16-bit little endian word.
138 inline uint_least16_t endian_little16 (const uint8_t ptr[2])
139 {
140  return endian_16 (ptr[1], ptr[0]);
141 }
142 
143 // Write a little-endian 16-bit word to two bytes in memory.
144 inline void endian_little16 (uint8_t ptr[2], uint_least16_t word)
145 {
146  ptr[0] = endian_16lo8 (word);
147  ptr[1] = endian_16hi8 (word);
148 }
149 
150 // Convert high-byte and low-byte to 16-bit big endian word.
151 inline uint_least16_t endian_big16 (const uint8_t ptr[2])
152 {
153  return endian_16 (ptr[0], ptr[1]);
154 }
155 
156 // Write a little-big 16-bit word to two bytes in memory.
157 inline void endian_big16 (uint8_t ptr[2], uint_least16_t word)
158 {
159  ptr[0] = endian_16hi8 (word);
160  ptr[1] = endian_16lo8 (word);
161 }
162 
163 
165 // INT32 FUNCTIONS
167 // Set the lo word (16bit) in a dword (32 bit)
168 inline void endian_32lo16 (uint_least32_t &dword, uint_least16_t word)
169 {
170  dword &= (uint_least32_t) 0xffff0000;
171  dword |= word;
172 }
173 
174 // Get the lo word (16bit) in a dword (32 bit)
175 inline uint_least16_t endian_32lo16 (uint_least32_t dword)
176 {
177  return (uint_least16_t) dword & 0xffff;
178 }
179 
180 // Set the hi word (16bit) in a dword (32 bit)
181 inline void endian_32hi16 (uint_least32_t &dword, uint_least16_t word)
182 {
183  dword &= (uint_least32_t) 0x0000ffff;
184  dword |= (uint_least32_t) word << 16;
185 }
186 
187 // Get the hi word (16bit) in a dword (32 bit)
188 inline uint_least16_t endian_32hi16 (uint_least32_t dword)
189 {
190  return (uint_least16_t) (dword >> 16);
191 }
192 
193 // Set the lo byte (8 bit) in a dword (32 bit)
194 inline void endian_32lo8 (uint_least32_t &dword, uint8_t byte)
195 {
196  dword &= (uint_least32_t) 0xffffff00;
197  dword |= (uint_least32_t) byte;
198 }
199 
200 // Get the lo byte (8 bit) in a dword (32 bit)
201 inline uint8_t endian_32lo8 (uint_least32_t dword)
202 {
203  return (uint8_t) dword;
204 }
205 
206 // Set the hi byte (8 bit) in a dword (32 bit)
207 inline void endian_32hi8 (uint_least32_t &dword, uint8_t byte)
208 {
209  dword &= (uint_least32_t) 0xffff00ff;
210  dword |= (uint_least32_t) byte << 8;
211 }
212 
213 // Get the hi byte (8 bit) in a dword (32 bit)
214 inline uint8_t endian_32hi8 (uint_least32_t dword)
215 {
216  return (uint8_t) (dword >> 8);
217 }
218 
219 // Swap hi and lo words endian in 32 bit dword.
220 inline void endian_32swap16 (uint_least32_t &dword)
221 {
222  uint_least16_t lo = endian_32lo16 (dword);
223  uint_least16_t hi = endian_32hi16 (dword);
224  endian_32lo16 (dword, hi);
225  endian_32hi16 (dword, lo);
226 }
227 
228 // Swap word endian.
229 inline void endian_32swap8 (uint_least32_t &dword)
230 {
231  uint_least16_t lo = 0, hi = 0;
232  lo = endian_32lo16 (dword);
233  hi = endian_32hi16 (dword);
234  endian_16swap8 (lo);
235  endian_16swap8 (hi);
236  endian_32lo16 (dword, hi);
237  endian_32hi16 (dword, lo);
238 }
239 
240 // Convert high-byte and low-byte to 32-bit word.
241 inline uint_least32_t endian_32 (uint8_t hihi, uint8_t hilo, uint8_t hi, uint8_t lo)
242 {
243  uint_least32_t dword = 0;
244  uint_least16_t word = 0;
245  endian_32lo8 (dword, lo);
246  endian_32hi8 (dword, hi);
247  endian_16lo8 (word, hilo);
248  endian_16hi8 (word, hihi);
249  endian_32hi16 (dword, word);
250  return dword;
251 }
252 
253 // Convert high-byte and low-byte to 32-bit little endian word.
254 inline uint_least32_t endian_little32 (const uint8_t ptr[4])
255 {
256  return endian_32 (ptr[3], ptr[2], ptr[1], ptr[0]);
257 }
258 
259 // Write a little-endian 32-bit word to four bytes in memory.
260 inline void endian_little32 (uint8_t ptr[4], uint_least32_t dword)
261 {
262  uint_least16_t word = 0;
263  ptr[0] = endian_32lo8 (dword);
264  ptr[1] = endian_32hi8 (dword);
265  word = endian_32hi16 (dword);
266  ptr[2] = endian_16lo8 (word);
267  ptr[3] = endian_16hi8 (word);
268 }
269 
270 // Convert high-byte and low-byte to 32-bit big endian word.
271 inline uint_least32_t endian_big32 (const uint8_t ptr[4])
272 {
273  return endian_32 (ptr[0], ptr[1], ptr[2], ptr[3]);
274 }
275 
276 // Write a big-endian 32-bit word to four bytes in memory.
277 inline void endian_big32 (uint8_t ptr[4], uint_least32_t dword)
278 {
279  uint_least16_t word = 0;
280  word = endian_32hi16 (dword);
281  ptr[1] = endian_16lo8 (word);
282  ptr[0] = endian_16hi8 (word);
283  ptr[2] = endian_32hi8 (dword);
284  ptr[3] = endian_32lo8 (dword);
285 }
286 
287 #endif // _sidendian_h_
288 
289