1 /*
   2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright 2012, 2013 SAP AG. 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   // Returns true, if the byte ordering used by Java is different from the native byte ordering
  41   // of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc.
  42   static inline bool is_Java_byte_ordering_different() { return true; }
  43 
  44   // Forward declarations of the compiler-dependent implementation
  45   static inline u2 swap_u2(u2 x);
  46   static inline u4 swap_u4(u4 x);
  47   static inline u8 swap_u8(u8 x);
  48 
  49   // TODO(asmundak): PowerPC64 supports unaligned reads/writes, investigate whether explicit
  50   // byte manipulation is needed.
  51   static inline u2   get_native_u2(address p) {
  52     return (intptr_t(p) & 1) == 0
  53              ?   *(u2*)p
  54              :   ( u2(p[1]) << 8 )
  55                | ( u2(p[0])      );
  56   }
  57 
  58   static inline u4   get_native_u4(address p) {
  59     switch (intptr_t(p) & 3) {
  60      case 0:  return *(u4*)p;
  61 
  62      case 2:  return (  u4( ((u2*)p)[1] ) << 16  )
  63                    | (  u4( ((u2*)p)[0] )        );
  64 
  65     default:  return ( u4(p[3]) << 24 )
  66                    | ( u4(p[2]) << 16 )
  67                    | ( u4(p[1]) <<  8 )
  68                    |   u4(p[0]);
  69     }
  70   }
  71 
  72   static inline u8   get_native_u8(address p) {
  73     switch (intptr_t(p) & 7) {
  74       case 0:  return *(u8*)p;
  75 
  76       case 4:  return (  u8( ((u4*)p)[1] ) << 32  )
  77                     | (  u8( ((u4*)p)[0] )        );
  78 
  79       case 2:  return (  u8( ((u2*)p)[3] ) << 48  )
  80                     | (  u8( ((u2*)p)[2] ) << 32  )
  81                     | (  u8( ((u2*)p)[1] ) << 16  )
  82                     | (  u8( ((u2*)p)[0] )        );
  83 
  84      default:  return ( u8(p[7]) << 56 )
  85                     | ( u8(p[6]) << 48 )
  86                     | ( u8(p[5]) << 40 )
  87                     | ( u8(p[4]) << 32 )
  88                     | ( u8(p[3]) << 24 )
  89                     | ( u8(p[2]) << 16 )
  90                     | ( u8(p[1]) <<  8 )
  91                     |   u8(p[0]);
  92     }
  93   }
  94 
  95 
  96 
  97   static inline void put_native_u2(address p, u2 x) {
  98     if ( (intptr_t(p) & 1) == 0 )  *(u2*)p = x;
  99     else {
 100       p[1] = x >> 8;
 101       p[0] = x;
 102     }
 103   }
 104 
 105   static inline void put_native_u4(address p, u4 x) {
 106     switch ( intptr_t(p) & 3 ) {
 107     case 0:  *(u4*)p = x;
 108               break;
 109 
 110     case 2:  ((u2*)p)[1] = x >> 16;
 111              ((u2*)p)[0] = x;
 112              break;
 113 
 114     default: ((u1*)p)[3] = x >> 24;
 115              ((u1*)p)[2] = x >> 16;
 116              ((u1*)p)[1] = x >>  8;
 117              ((u1*)p)[0] = x;
 118              break;
 119     }
 120   }
 121 
 122   static inline void put_native_u8(address p, u8 x) {
 123     switch ( intptr_t(p) & 7 ) {
 124     case 0:  *(u8*)p = x;
 125              break;
 126 
 127     case 4:  ((u4*)p)[1] = x >> 32;
 128              ((u4*)p)[0] = x;
 129              break;
 130 
 131     case 2:  ((u2*)p)[3] = x >> 48;
 132              ((u2*)p)[2] = x >> 32;
 133              ((u2*)p)[1] = x >> 16;
 134              ((u2*)p)[0] = x;
 135              break;
 136 
 137     default: ((u1*)p)[7] = x >> 56;
 138              ((u1*)p)[6] = x >> 48;
 139              ((u1*)p)[5] = x >> 40;
 140              ((u1*)p)[4] = x >> 32;
 141              ((u1*)p)[3] = x >> 24;
 142              ((u1*)p)[2] = x >> 16;
 143              ((u1*)p)[1] = x >>  8;
 144              ((u1*)p)[0] = x;
 145     }
 146   }
 147 
 148   // Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering)
 149   // (no byte-order reversal is needed since Power CPUs are big-endian oriented).
 150   static inline u2   get_Java_u2(address p) { return swap_u2(get_native_u2(p)); }
 151   static inline u4   get_Java_u4(address p) { return swap_u4(get_native_u4(p)); }
 152   static inline u8   get_Java_u8(address p) { return swap_u8(get_native_u8(p)); }
 153 
 154   static inline void put_Java_u2(address p, u2 x)     { put_native_u2(p, swap_u2(x)); }
 155   static inline void put_Java_u4(address p, u4 x)     { put_native_u4(p, swap_u4(x)); }
 156   static inline void put_Java_u8(address p, u8 x)     { put_native_u8(p, swap_u8(x)); }
 157 
 158 #else // !defined(VM_LITTLE_ENDIAN)
 159 
 160   // Returns true, if the byte ordering used by Java is different from the nativ byte ordering
 161   // of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc.
 162   static inline bool is_Java_byte_ordering_different() { return false; }
 163 
 164   // Thus, a swap between native and Java ordering is always a no-op:
 165   static inline u2   swap_u2(u2 x)  { return x; }
 166   static inline u4   swap_u4(u4 x)  { return x; }
 167   static inline u8   swap_u8(u8 x)  { return x; }
 168 
 169   static inline u2   get_native_u2(address p) {
 170     return (intptr_t(p) & 1) == 0
 171              ?   *(u2*)p
 172              :   ( u2(p[0]) << 8 )
 173                | ( u2(p[1])      );
 174   }
 175 
 176   static inline u4   get_native_u4(address p) {
 177     switch (intptr_t(p) & 3) {
 178      case 0:  return *(u4*)p;
 179 
 180      case 2:  return (  u4( ((u2*)p)[0] ) << 16  )
 181                    | (  u4( ((u2*)p)[1] )        );
 182 
 183     default:  return ( u4(p[0]) << 24 )
 184                    | ( u4(p[1]) << 16 )
 185                    | ( u4(p[2]) <<  8 )
 186                    |   u4(p[3]);
 187     }
 188   }
 189 
 190   static inline u8   get_native_u8(address p) {
 191     switch (intptr_t(p) & 7) {
 192       case 0:  return *(u8*)p;
 193 
 194       case 4:  return (  u8( ((u4*)p)[0] ) << 32  )
 195                     | (  u8( ((u4*)p)[1] )        );
 196 
 197       case 2:  return (  u8( ((u2*)p)[0] ) << 48  )
 198                     | (  u8( ((u2*)p)[1] ) << 32  )
 199                     | (  u8( ((u2*)p)[2] ) << 16  )
 200                     | (  u8( ((u2*)p)[3] )        );
 201 
 202      default:  return ( u8(p[0]) << 56 )
 203                     | ( u8(p[1]) << 48 )
 204                     | ( u8(p[2]) << 40 )
 205                     | ( u8(p[3]) << 32 )
 206                     | ( u8(p[4]) << 24 )
 207                     | ( u8(p[5]) << 16 )
 208                     | ( u8(p[6]) <<  8 )
 209                     |   u8(p[7]);
 210     }
 211   }
 212 
 213 
 214 
 215   static inline void put_native_u2(address p, u2 x) {
 216     if ( (intptr_t(p) & 1) == 0 ) { *(u2*)p = x; }
 217     else {
 218       p[0] = x >> 8;
 219       p[1] = x;
 220     }
 221   }
 222 
 223   static inline void put_native_u4(address p, u4 x) {
 224     switch ( intptr_t(p) & 3 ) {
 225     case 0:  *(u4*)p = x;
 226               break;
 227 
 228     case 2:  ((u2*)p)[0] = x >> 16;
 229              ((u2*)p)[1] = x;
 230              break;
 231 
 232     default: ((u1*)p)[0] = x >> 24;
 233              ((u1*)p)[1] = x >> 16;
 234              ((u1*)p)[2] = x >>  8;
 235              ((u1*)p)[3] = x;
 236              break;
 237     }
 238   }
 239 
 240   static inline void put_native_u8(address p, u8 x) {
 241     switch ( intptr_t(p) & 7 ) {
 242     case 0:  *(u8*)p = x;
 243              break;
 244 
 245     case 4:  ((u4*)p)[0] = x >> 32;
 246              ((u4*)p)[1] = x;
 247              break;
 248 
 249     case 2:  ((u2*)p)[0] = x >> 48;
 250              ((u2*)p)[1] = x >> 32;
 251              ((u2*)p)[2] = x >> 16;
 252              ((u2*)p)[3] = x;
 253              break;
 254 
 255     default: ((u1*)p)[0] = x >> 56;
 256              ((u1*)p)[1] = x >> 48;
 257              ((u1*)p)[2] = x >> 40;
 258              ((u1*)p)[3] = x >> 32;
 259              ((u1*)p)[4] = x >> 24;
 260              ((u1*)p)[5] = x >> 16;
 261              ((u1*)p)[6] = x >>  8;
 262              ((u1*)p)[7] = x;
 263     }
 264   }
 265 
 266   // Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering)
 267   // (no byte-order reversal is needed since Power CPUs are big-endian oriented).
 268   static inline u2   get_Java_u2(address p) { return get_native_u2(p); }
 269   static inline u4   get_Java_u4(address p) { return get_native_u4(p); }
 270   static inline u8   get_Java_u8(address p) { return get_native_u8(p); }
 271 
 272   static inline void put_Java_u2(address p, u2 x)     { put_native_u2(p, x); }
 273   static inline void put_Java_u4(address p, u4 x)     { put_native_u4(p, x); }
 274   static inline void put_Java_u8(address p, u8 x)     { put_native_u8(p, x); }
 275 
 276 #endif // VM_LITTLE_ENDIAN
 277 };
 278 
 279 #include "bytes_linux_ppc.inline.hpp"
 280 
 281 #endif // CPU_PPC_VM_BYTES_PPC_HPP