1/*
2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of Oracle nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "endian.hpp"
33#include "inttypes.hpp"
34
35// Most modern compilers optimize the bswap routines to native instructions.
36inline static u2 bswap_16(u2 x) {
37 return ((x & 0xFF) << 8) |
38 ((x >> 8) & 0xFF);
39}
40
41inline static u4 bswap_32(u4 x) {
42 return ((x & 0xFF) << 24) |
43 ((x & 0xFF00) << 8) |
44 ((x >> 8) & 0xFF00) |
45 ((x >> 24) & 0xFF);
46}
47
48inline static u8 bswap_64(u8 x) {
49 return (u8)bswap_32((u4)x) << 32 |
50 (u8)bswap_32((u4)(x >> 32));
51}
52
53u2 NativeEndian::get(u2 x) { return x; }
54u4 NativeEndian::get(u4 x) { return x; }
55u8 NativeEndian::get(u8 x) { return x; }
56s2 NativeEndian::get(s2 x) { return x; }
57s4 NativeEndian::get(s4 x) { return x; }
58s8 NativeEndian::get(s8 x) { return x; }
59
60void NativeEndian::set(u2& x, u2 y) { x = y; }
61void NativeEndian::set(u4& x, u4 y) { x = y; }
62void NativeEndian::set(u8& x, u8 y) { x = y; }
63void NativeEndian::set(s2& x, s2 y) { x = y; }
64void NativeEndian::set(s4& x, s4 y) { x = y; }
65void NativeEndian::set(s8& x, s8 y) { x = y; }
66
67NativeEndian NativeEndian::_native;
68
69u2 SwappingEndian::get(u2 x) { return bswap_16(x); }
70u4 SwappingEndian::get(u4 x) { return bswap_32(x); }
71u8 SwappingEndian::get(u8 x) { return bswap_64(x); }
72s2 SwappingEndian::get(s2 x) { return bswap_16(x); }
73s4 SwappingEndian::get(s4 x) { return bswap_32(x); }
74s8 SwappingEndian::get(s8 x) { return bswap_64(x); }
75
76void SwappingEndian::set(u2& x, u2 y) { x = bswap_16(y); }
77void SwappingEndian::set(u4& x, u4 y) { x = bswap_32(y); }
78void SwappingEndian::set(u8& x, u8 y) { x = bswap_64(y); }
79void SwappingEndian::set(s2& x, s2 y) { x = bswap_16(y); }
80void SwappingEndian::set(s4& x, s4 y) { x = bswap_32(y); }
81void SwappingEndian::set(s8& x, s8 y) { x = bswap_64(y); }
82
83SwappingEndian SwappingEndian::_swapping;
84
85Endian* Endian::get_handler(bool big_endian) {
86 // If requesting little endian on a little endian machine or
87 // big endian on a big endian machine use native handler
88 if (big_endian == is_big_endian()) {
89 return NativeEndian::get_native();
90 } else {
91 // Use swapping handler.
92 return SwappingEndian::get_swapping();
93 }
94}
95
96// Return a platform u2 from an array in which Big Endian is applied.
97u2 Endian::get_java(u1* x) {
98 return (u2) (x[0]<<8 | x[1]);
99}
100
101// Add a platform u2 to the array as a Big Endian u2
102void Endian::set_java(u1* p, u2 x) {
103 p[0] = (x >> 8) & 0xff;
104 p[1] = x & 0xff;
105}
106
107Endian* Endian::get_native_handler() {
108 return NativeEndian::get_native();
109}
110