1 /*
2  * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
3  * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.
9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  *
24  */
25 
26 #ifndef CPU_PPC_VM_BYTES_PPC_HPP
27 #define CPU_PPC_VM_BYTES_PPC_HPP
28 
29 #include "memory/allocation.hpp"
30 
31 class Bytes: AllStatic {
32  public:
33   // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering
34   // PowerPC needs to check for alignment.
35 
36   // Can I count on address always being a pointer to an unsigned char? Yes.
37 
38 #if defined(VM_LITTLE_ENDIAN)
39 
40   // Forward declarations of the compiler-dependent implementation
41   static inline u2 swap_u2(u2 x);
42   static inline u4 swap_u4(u4 x);
43   static inline u8 swap_u8(u8 x);
44 
get_native_u2(address p)45   static inline u2   get_native_u2(address p) {
46     return (intptr_t(p) & 1) == 0
47              ?   *(u2*)p
48              :   ( u2(p[1]) << 8 )
49                | ( u2(p[0])      );
50   }
51 
get_native_u4(address p)52   static inline u4   get_native_u4(address p) {
53     switch (intptr_t(p) & 3) {
54      case 0:  return *(u4*)p;
55 
56      case 2:  return (  u4( ((u2*)p)[1] ) << 16  )
57                    | (  u4( ((u2*)p)[0] )        );
58 
59     default:  return ( u4(p[3]) << 24 )
60                    | ( u4(p[2]) << 16 )
61                    | ( u4(p[1]) <<  8 )
62                    |   u4(p[0]);
63     }
64   }
65 
get_native_u8(address p)66   static inline u8   get_native_u8(address p) {
67     switch (intptr_t(p) & 7) {
68       case 0:  return *(u8*)p;
69 
70       case 4:  return (  u8( ((u4*)p)[1] ) << 32  )
71                     | (  u8( ((u4*)p)[0] )        );
72 
73       case 2:  return (  u8( ((u2*)p)[3] ) << 48  )
74                     | (  u8( ((u2*)p)[2] ) << 32  )
75                     | (  u8( ((u2*)p)[1] ) << 16  )
76                     | (  u8( ((u2*)p)[0] )        );
77 
78      default:  return ( u8(p[7]) << 56 )
79                     | ( u8(p[6]) << 48 )
80                     | ( u8(p[5]) << 40 )
81                     | ( u8(p[4]) << 32 )
82                     | ( u8(p[3]) << 24 )
83                     | ( u8(p[2]) << 16 )
84                     | ( u8(p[1]) <<  8 )
85                     |   u8(p[0]);
86     }
87   }
88 
89 
90 
put_native_u2(address p,u2 x)91   static inline void put_native_u2(address p, u2 x) {
92     if ( (intptr_t(p) & 1) == 0 )  *(u2*)p = x;
93     else {
94       p[1] = x >> 8;
95       p[0] = x;
96     }
97   }
98 
put_native_u4(address p,u4 x)99   static inline void put_native_u4(address p, u4 x) {
100     switch ( intptr_t(p) & 3 ) {
101     case 0:  *(u4*)p = x;
102               break;
103 
104     case 2:  ((u2*)p)[1] = x >> 16;
105              ((u2*)p)[0] = x;
106              break;
107 
108     default: ((u1*)p)[3] = x >> 24;
109              ((u1*)p)[2] = x >> 16;
110              ((u1*)p)[1] = x >>  8;
111              ((u1*)p)[0] = x;
112              break;
113     }
114   }
115 
put_native_u8(address p,u8 x)116   static inline void put_native_u8(address p, u8 x) {
117     switch ( intptr_t(p) & 7 ) {
118     case 0:  *(u8*)p = x;
119              break;
120 
121     case 4:  ((u4*)p)[1] = x >> 32;
122              ((u4*)p)[0] = x;
123              break;
124 
125     case 2:  ((u2*)p)[3] = x >> 48;
126              ((u2*)p)[2] = x >> 32;
127              ((u2*)p)[1] = x >> 16;
128              ((u2*)p)[0] = x;
129              break;
130 
131     default: ((u1*)p)[7] = x >> 56;
132              ((u1*)p)[6] = x >> 48;
133              ((u1*)p)[5] = x >> 40;
134              ((u1*)p)[4] = x >> 32;
135              ((u1*)p)[3] = x >> 24;
136              ((u1*)p)[2] = x >> 16;
137              ((u1*)p)[1] = x >>  8;
138              ((u1*)p)[0] = x;
139     }
140   }
141 
142   // Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering)
143   // (no byte-order reversal is needed since Power CPUs are big-endian oriented).
get_Java_u2(address p)144   static inline u2   get_Java_u2(address p) { return swap_u2(get_native_u2(p)); }
get_Java_u4(address p)145   static inline u4   get_Java_u4(address p) { return swap_u4(get_native_u4(p)); }
get_Java_u8(address p)146   static inline u8   get_Java_u8(address p) { return swap_u8(get_native_u8(p)); }
147 
put_Java_u2(address p,u2 x)148   static inline void put_Java_u2(address p, u2 x)     { put_native_u2(p, swap_u2(x)); }
put_Java_u4(address p,u4 x)149   static inline void put_Java_u4(address p, u4 x)     { put_native_u4(p, swap_u4(x)); }
put_Java_u8(address p,u8 x)150   static inline void put_Java_u8(address p, u8 x)     { put_native_u8(p, swap_u8(x)); }
151 
152 #else // !defined(VM_LITTLE_ENDIAN)
153 
154   // Thus, a swap between native and Java ordering is always a no-op:
155   static inline u2   swap_u2(u2 x)  { return x; }
156   static inline u4   swap_u4(u4 x)  { return x; }
157   static inline u8   swap_u8(u8 x)  { return x; }
158 
159   static inline u2   get_native_u2(address p) {
160     return (intptr_t(p) & 1) == 0
161              ?   *(u2*)p
162              :   ( u2(p[0]) << 8 )
163                | ( u2(p[1])      );
164   }
165 
166   static inline u4   get_native_u4(address p) {
167     switch (intptr_t(p) & 3) {
168      case 0:  return *(u4*)p;
169 
170      case 2:  return (  u4( ((u2*)p)[0] ) << 16  )
171                    | (  u4( ((u2*)p)[1] )        );
172 
173     default:  return ( u4(p[0]) << 24 )
174                    | ( u4(p[1]) << 16 )
175                    | ( u4(p[2]) <<  8 )
176                    |   u4(p[3]);
177     }
178   }
179 
180   static inline u8   get_native_u8(address p) {
181     switch (intptr_t(p) & 7) {
182       case 0:  return *(u8*)p;
183 
184       case 4:  return (  u8( ((u4*)p)[0] ) << 32  )
185                     | (  u8( ((u4*)p)[1] )        );
186 
187       case 2:  return (  u8( ((u2*)p)[0] ) << 48  )
188                     | (  u8( ((u2*)p)[1] ) << 32  )
189                     | (  u8( ((u2*)p)[2] ) << 16  )
190                     | (  u8( ((u2*)p)[3] )        );
191 
192      default:  return ( u8(p[0]) << 56 )
193                     | ( u8(p[1]) << 48 )
194                     | ( u8(p[2]) << 40 )
195                     | ( u8(p[3]) << 32 )
196                     | ( u8(p[4]) << 24 )
197                     | ( u8(p[5]) << 16 )
198                     | ( u8(p[6]) <<  8 )
199                     |   u8(p[7]);
200     }
201   }
202 
203 
204 
205   static inline void put_native_u2(address p, u2 x) {
206     if ( (intptr_t(p) & 1) == 0 ) { *(u2*)p = x; }
207     else {
208       p[0] = x >> 8;
209       p[1] = x;
210     }
211   }
212 
213   static inline void put_native_u4(address p, u4 x) {
214     switch ( intptr_t(p) & 3 ) {
215     case 0:  *(u4*)p = x;
216               break;
217 
218     case 2:  ((u2*)p)[0] = x >> 16;
219              ((u2*)p)[1] = x;
220              break;
221 
222     default: ((u1*)p)[0] = x >> 24;
223              ((u1*)p)[1] = x >> 16;
224              ((u1*)p)[2] = x >>  8;
225              ((u1*)p)[3] = x;
226              break;
227     }
228   }
229 
230   static inline void put_native_u8(address p, u8 x) {
231     switch ( intptr_t(p) & 7 ) {
232     case 0:  *(u8*)p = x;
233              break;
234 
235     case 4:  ((u4*)p)[0] = x >> 32;
236              ((u4*)p)[1] = x;
237              break;
238 
239     case 2:  ((u2*)p)[0] = x >> 48;
240              ((u2*)p)[1] = x >> 32;
241              ((u2*)p)[2] = x >> 16;
242              ((u2*)p)[3] = x;
243              break;
244 
245     default: ((u1*)p)[0] = x >> 56;
246              ((u1*)p)[1] = x >> 48;
247              ((u1*)p)[2] = x >> 40;
248              ((u1*)p)[3] = x >> 32;
249              ((u1*)p)[4] = x >> 24;
250              ((u1*)p)[5] = x >> 16;
251              ((u1*)p)[6] = x >>  8;
252              ((u1*)p)[7] = x;
253     }
254   }
255 
256   // Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering)
257   // (no byte-order reversal is needed since Power CPUs are big-endian oriented).
258   static inline u2   get_Java_u2(address p) { return get_native_u2(p); }
259   static inline u4   get_Java_u4(address p) { return get_native_u4(p); }
260   static inline u8   get_Java_u8(address p) { return get_native_u8(p); }
261 
262   static inline void put_Java_u2(address p, u2 x)     { put_native_u2(p, x); }
263   static inline void put_Java_u4(address p, u4 x)     { put_native_u4(p, x); }
264   static inline void put_Java_u8(address p, u8 x)     { put_native_u8(p, x); }
265 
266 #endif // VM_LITTLE_ENDIAN
267 };
268 
269 #include OS_CPU_HEADER_INLINE(bytes)
270 
271 #endif // CPU_PPC_VM_BYTES_PPC_HPP
272