libsidplayfp  1.8.7
sidendian.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2000 Simon White
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 
22 #ifndef SIDENDIAN_H
23 #define SIDENDIAN_H
24 
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28 
29 // NOTE: The optimisations in this file rely on the structure of memory
30 // e.g. 2 shorts being contained in 1 long. Although these sizes are
31 // checked to make sure the optimisation is ok, gcc 2.96 (and above)
32 // introduced better optimisations. This results in caching of values
33 // in internal registers and therefore writes to ram through the aliases
34 // not being reflected in the CPU regs. The use of the volatile keyword
35 // fixes this.
36 
37 #include <stdint.h>
38 
39 /*
40 Labeling:
41 0 - LO
42 1 - HI
43 2 - HILO
44 3 - HIHI
45 */
46 
48 // INT16 FUNCTIONS
51 inline void endian_16lo8 (uint_least16_t &word, uint8_t byte)
52 {
53  word &= 0xff00;
54  word |= byte;
55 }
56 
58 inline uint8_t endian_16lo8 (uint_least16_t word)
59 {
60  return (uint8_t) word;
61 }
62 
64 inline void endian_16hi8 (uint_least16_t &word, uint8_t byte)
65 {
66  word &= 0x00ff;
67  word |= (uint_least16_t) byte << 8;
68 }
69 
71 inline uint8_t endian_16hi8 (uint_least16_t word)
72 {
73  return (uint8_t) (word >> 8);
74 }
75 
77 inline void endian_16swap8 (uint_least16_t &word)
78 {
79  uint8_t lo = endian_16lo8 (word);
80  uint8_t hi = endian_16hi8 (word);
81  endian_16lo8 (word, hi);
82  endian_16hi8 (word, lo);
83 }
84 
86 inline uint_least16_t endian_16 (uint8_t hi, uint8_t lo)
87 {
88  uint_least16_t word = 0;
89  endian_16lo8 (word, lo);
90  endian_16hi8 (word, hi);
91  return word;
92 }
93 
95 inline void endian_16 (uint8_t ptr[2], uint_least16_t word)
96 {
97 # if defined(WORDS_BIGENDIAN)
98  ptr[0] = endian_16hi8 (word);
99  ptr[1] = endian_16lo8 (word);
100 # else
101  ptr[0] = endian_16lo8 (word);
102  ptr[1] = endian_16hi8 (word);
103 # endif
104 }
105 
106 inline void endian_16 (char ptr[2], uint_least16_t word)
107 {
108  endian_16 ((uint8_t *) ptr, word);
109 }
110 
112 inline uint_least16_t endian_little16 (const uint8_t ptr[2])
113 {
114  return endian_16 (ptr[1], ptr[0]);
115 }
116 
118 inline void endian_little16 (uint8_t ptr[2], uint_least16_t word)
119 {
120  ptr[0] = endian_16lo8 (word);
121  ptr[1] = endian_16hi8 (word);
122 }
123 
125 inline uint_least16_t endian_big16 (const uint8_t ptr[2])
126 {
127  return endian_16 (ptr[0], ptr[1]);
128 }
129 
131 inline void endian_big16 (uint8_t ptr[2], uint_least16_t word)
132 {
133  ptr[0] = endian_16hi8 (word);
134  ptr[1] = endian_16lo8 (word);
135 }
136 
137 
139 // INT32 FUNCTIONS
142 inline void endian_32lo16 (uint_least32_t &dword, uint_least16_t word)
143 {
144  dword &= (uint_least32_t) 0xffff0000;
145  dword |= word;
146 }
147 
149 inline uint_least16_t endian_32lo16 (uint_least32_t dword)
150 {
151  return (uint_least16_t) dword & 0xffff;
152 }
153 
155 inline void endian_32hi16 (uint_least32_t &dword, uint_least16_t word)
156 {
157  dword &= (uint_least32_t) 0x0000ffff;
158  dword |= (uint_least32_t) word << 16;
159 }
160 
162 inline uint_least16_t endian_32hi16 (uint_least32_t dword)
163 {
164  return (uint_least16_t) (dword >> 16);
165 }
166 
168 inline void endian_32lo8 (uint_least32_t &dword, uint8_t byte)
169 {
170  dword &= (uint_least32_t) 0xffffff00;
171  dword |= (uint_least32_t) byte;
172 }
173 
175 inline uint8_t endian_32lo8 (uint_least32_t dword)
176 {
177  return (uint8_t) dword;
178 }
179 
181 inline void endian_32hi8 (uint_least32_t &dword, uint8_t byte)
182 {
183  dword &= (uint_least32_t) 0xffff00ff;
184  dword |= (uint_least32_t) byte << 8;
185 }
186 
188 inline uint8_t endian_32hi8 (uint_least32_t dword)
189 {
190  return (uint8_t) (dword >> 8);
191 }
192 
194 inline void endian_32swap16 (uint_least32_t &dword)
195 {
196  uint_least16_t lo = endian_32lo16 (dword);
197  uint_least16_t hi = endian_32hi16 (dword);
198  endian_32lo16 (dword, hi);
199  endian_32hi16 (dword, lo);
200 }
201 
203 inline void endian_32swap8 (uint_least32_t &dword)
204 {
205  uint_least16_t lo = 0, hi = 0;
206  lo = endian_32lo16 (dword);
207  hi = endian_32hi16 (dword);
208  endian_16swap8 (lo);
209  endian_16swap8 (hi);
210  endian_32lo16 (dword, hi);
211  endian_32hi16 (dword, lo);
212 }
213 
215 inline uint_least32_t endian_32 (uint8_t hihi, uint8_t hilo, uint8_t hi, uint8_t lo)
216 {
217  uint_least32_t dword = 0;
218  uint_least16_t word = 0;
219  endian_32lo8 (dword, lo);
220  endian_32hi8 (dword, hi);
221  endian_16lo8 (word, hilo);
222  endian_16hi8 (word, hihi);
223  endian_32hi16 (dword, word);
224  return dword;
225 }
226 
228 inline uint_least32_t endian_little32 (const uint8_t ptr[4])
229 {
230  return endian_32 (ptr[3], ptr[2], ptr[1], ptr[0]);
231 }
232 
234 inline void endian_little32 (uint8_t ptr[4], uint_least32_t dword)
235 {
236  uint_least16_t word = 0;
237  ptr[0] = endian_32lo8 (dword);
238  ptr[1] = endian_32hi8 (dword);
239  word = endian_32hi16 (dword);
240  ptr[2] = endian_16lo8 (word);
241  ptr[3] = endian_16hi8 (word);
242 }
243 
245 inline uint_least32_t endian_big32 (const uint8_t ptr[4])
246 {
247  return endian_32 (ptr[0], ptr[1], ptr[2], ptr[3]);
248 }
249 
251 inline void endian_big32 (uint8_t ptr[4], uint_least32_t dword)
252 {
253  uint_least16_t word = 0;
254  word = endian_32hi16 (dword);
255  ptr[1] = endian_16lo8 (word);
256  ptr[0] = endian_16hi8 (word);
257  ptr[2] = endian_32hi8 (dword);
258  ptr[3] = endian_32lo8 (dword);
259 }
260 
261 #endif // SIDENDIAN_H