Line data Source code
1 : /* src/toolbox/endianess.hpp - utilities for reading/writing to/from a
2 : buffer in little or big endian
3 :
4 : Copyright (C) 1996-2013
5 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 :
7 : This file is part of CACAO.
8 :
9 : This program is free software; you can redistribute it and/or
10 : modify it under the terms of the GNU General Public License as
11 : published by the Free Software Foundation; either version 2, or (at
12 : your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful, but
15 : WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program; if not, write to the Free Software
21 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 : 02110-1301, USA.
23 :
24 : */
25 :
26 : #ifndef CACAO_ENDIANESS_
27 : #define CACAO_ENDIANESS_ 1
28 :
29 : #include "mm/memory.hpp"
30 : #include "toolbox/assert.hpp"
31 : #include "vm/types.hpp"
32 :
33 : namespace cacao {
34 : // ***** READ UNSIGNED, LITTLE ENDIAN **************************************
35 :
36 : #if defined(__I386__) || defined(__X86_64__)
37 :
38 : // we can optimize the LE access on little endian machines without alignment
39 :
40 : static inline uint8_t read_u1_le(const uint8_t *src) { return *src; }
41 5346826 : static inline uint16_t read_u2_le(const uint8_t *src) { return *((uint16_t*) src); }
42 5285316 : static inline uint32_t read_u4_le(const uint8_t *src) { return *((uint32_t*) src); }
43 : static inline uint64_t read_u8_le(const uint8_t *src) { return *((uint64_t*) src); }
44 :
45 : #else // defined(__I386__) || defined(__X86_64__)
46 :
47 : static inline uint8_t read_u1_le(const uint8_t *src) {
48 : return *src;
49 : }
50 :
51 : static inline uint16_t read_u2_le(const uint8_t *src) {
52 : return (((uint16_t) src[1]) << 8) +
53 : ((uint16_t) src[0]);
54 : }
55 :
56 : static inline uint32_t read_u4_le(const uint8_t *src) {
57 : return (((uint32_t) src[3]) << 24) +
58 : (((uint32_t) src[2]) << 16) +
59 : (((uint32_t) src[1]) << 8) +
60 : ((uint32_t) src[0]);
61 : }
62 :
63 : static inline uint64_t read_u8_le(const uint8_t *src) {
64 : return (((uint64_t) src[7]) << 56) +
65 : (((uint64_t) src[6]) << 48) +
66 : (((uint64_t) src[5]) << 40) +
67 : (((uint64_t) src[4]) << 32) +
68 : (((uint64_t) src[3]) << 24) +
69 : (((uint64_t) src[2]) << 16) +
70 : (((uint64_t) src[1]) << 8) +
71 : ((uint64_t) src[0]);
72 : }
73 :
74 : #endif // defined(__I386__) || defined(__X86_64__)
75 :
76 : // ***** READ SIGNED, LITTLE ENDIAN ****************************************
77 :
78 : /// read int8_t from pointer little endian
79 : static inline int8_t read_s1_le(const uint8_t *src) { return (int8_t) read_u1_le(src); }
80 :
81 : /// read int16_t from pointer little endian
82 : static inline int16_t read_s2_le(const uint8_t *src) { return (int16_t) read_u2_le(src); }
83 :
84 : /// read int32_t from pointer little endian
85 : static inline int32_t read_s4_le(const uint8_t *src) { return (int32_t) read_u4_le(src); }
86 :
87 : /// read int64_t from pointer little endian
88 : static inline int64_t read_s8_le(const uint8_t *src) { return (int64_t) read_u8_le(src); }
89 :
90 : // ***** READ UNSIGNED, BIG ENDIAN (for Java class files ) *****************
91 :
92 : /// read uint8_t from pointer big endian
93 9690398 : static inline uint8_t read_u1_be(const uint8_t *src) {
94 9690398 : return *src;
95 : }
96 :
97 : /// read uint16_t from pointer big endian
98 17297288 : static inline uint16_t read_u2_be(const uint8_t *src) {
99 17297288 : return (((uint16_t) src[0]) << 8) +
100 17297288 : ((uint16_t) src[1]);
101 : }
102 :
103 : /// read uint32_t from pointer big endian
104 1646673 : static inline uint32_t read_u4_be(const uint8_t *src) {
105 1646673 : return (((uint32_t) src[0]) << 24) +
106 1646673 : (((uint32_t) src[1]) << 16) +
107 1646673 : (((uint32_t) src[2]) << 8) +
108 4940019 : ((uint32_t) src[3]);
109 : }
110 :
111 : /// read uint64_t from pointer big endian
112 10958 : static inline uint64_t read_u8_be(const uint8_t *src) {
113 10958 : return (((uint64_t) src[0]) << 56) +
114 10958 : (((uint64_t) src[1]) << 48) +
115 10958 : (((uint64_t) src[2]) << 40) +
116 10958 : (((uint64_t) src[3]) << 32) +
117 10958 : (((uint64_t) src[4]) << 24) +
118 10958 : (((uint64_t) src[5]) << 16) +
119 10958 : (((uint64_t) src[6]) << 8) +
120 76706 : ((uint64_t) src[7]);
121 : }
122 :
123 : // ***** READ SIGNED, BIG ENDIAN ************************
124 :
125 : /// read int8_t from pointer big endian
126 581103 : static inline int8_t read_s1_be(const uint8_t *src) { return (int8_t) read_u1_be(src); }
127 :
128 : /// read int16_t from pointer big endian
129 643789 : static inline int16_t read_s2_be(const uint8_t *src) { return (int16_t) read_u2_be(src); }
130 :
131 : /// read int32_t from pointer big endian
132 30763 : static inline int32_t read_s4_be(const uint8_t *src) { return (int32_t) read_u4_be(src); }
133 :
134 : /// read int64_t from pointer big endian
135 10958 : static inline int64_t read_s8_be(const uint8_t *src) { return (int64_t) read_u8_be(src); }
136 :
137 : // ***** READ FLOATING POINT, BIG ENDIAN ****************
138 :
139 2501 : static inline float read_float_be(const uint8_t *src) {
140 : EXPENSIVE_ASSERT(sizeof(float) == 4);
141 :
142 : float f;
143 :
144 : #if WORDS_BIGENDIAN == 0
145 : uint8_t buffer[4];
146 :
147 12505 : for (int i = 0; i < 4; i++)
148 10004 : buffer[3 - i] = read_u1_be(src + i);
149 :
150 2501 : MCOPY((uint8_t *) (&f), buffer, u1, 4);
151 : #else
152 : MCOPY((uint8_t *) (&f), src, u1, 4);
153 : #endif
154 :
155 2501 : return f;
156 : }
157 :
158 2033 : static inline double read_double_be(const uint8_t *src) {
159 : EXPENSIVE_ASSERT(sizeof(double) == 8);
160 :
161 : double d;
162 :
163 : #if WORDS_BIGENDIAN == 0
164 : uint8_t buffer[8];
165 :
166 : # if defined(__ARM__) && defined(__ARMEL__) && !defined(__VFP_FP__)
167 : // On little endian ARM processors when using FPA, word order
168 : // of doubles is still big endian. So take that into account
169 : // here. When using VFP, word order of doubles follows byte
170 : // order. (michi 2005/07/24)
171 :
172 : for (int i = 0; i < 4; i++)
173 : buffer[3 - i] = read_u1_be(src + i);
174 : for (int i = 0; i < 4; i++)
175 : buffer[7 - i] = read_u1_be(src + i + 4);
176 : # else
177 18297 : for (int i = 0; i < 8; i++)
178 16264 : buffer[7 - i] = read_u1_be(src + i);
179 : # endif
180 :
181 2033 : MCOPY((uint8_t *) (&d), buffer, u1, 8);
182 : #else
183 : MCOPY((uint8_t *) (&d), src, u1, 8);
184 : #endif
185 :
186 2033 : return d;
187 : }
188 : } // end namespace cacao
189 :
190 : #endif // CACAO_ENDIANESS_
191 :
192 : /*
193 : * These are local overrides for various environment variables in Emacs.
194 : * Please do not remove this and leave it at the end of the file, where
195 : * Emacs will automagically detect them.
196 : * ---------------------------------------------------------------------
197 : * Local variables:
198 : * mode: c++
199 : * indent-tabs-mode: t
200 : * c-basic-offset: 4
201 : * tab-width: 4
202 : * End:
203 : * vim:noexpandtab:sw=4:ts=4:
204 : */
|