• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_LIBPANDAFILE_BYTECODE_INSTRUCTION_INL_H_
17 #define PANDA_LIBPANDAFILE_BYTECODE_INSTRUCTION_INL_H_
18 
19 #include "bytecode_instruction.h"
20 #include "macros.h"
21 
22 namespace panda {
23 
24 template <const BytecodeInstMode Mode>
25 template <class R, class S>
ReadHelper(size_t byteoffset,size_t bytecount,size_t offset,size_t width)26 inline auto BytecodeInst<Mode>::ReadHelper(size_t byteoffset, size_t bytecount, size_t offset, size_t width) const
27 {
28     constexpr size_t BYTE_WIDTH = 8;
29 
30     size_t right_shift = offset % BYTE_WIDTH;
31 
32     S v = 0;
33     for (size_t i = 0; i < bytecount; i++) {
34         S mask = static_cast<S>(ReadByte(byteoffset + i)) << (i * BYTE_WIDTH);
35         v |= mask;
36     }
37 
38     v >>= right_shift;
39     size_t left_shift = sizeof(R) * BYTE_WIDTH - width;
40 
41     // Do sign extension using arithmetic shift. It's implementation defined,
42     // so we check such behavior using static assert.
43     // NOLINTNEXTLINE(hicpp-signed-bitwise)
44     static_assert((-1 >> 1) == -1);
45 
46     // NOLINTNEXTLINE(hicpp-signed-bitwise)
47     return static_cast<R>(v << left_shift) >> left_shift;
48 }
49 
50 template <const BytecodeInstMode Mode>
51 // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_COMMENT_LOCATION)
52 template <size_t offset, size_t width, bool is_signed /* = false */>
Read()53 inline auto BytecodeInst<Mode>::Read() const
54 {
55     constexpr size_t BYTE_WIDTH = 8;
56     constexpr size_t BYTE_OFFSET = offset / BYTE_WIDTH;
57     constexpr size_t BYTE_OFFSET_END = (offset + width + BYTE_WIDTH - 1) / BYTE_WIDTH;
58     constexpr size_t BYTE_COUNT = BYTE_OFFSET_END - BYTE_OFFSET;
59 
60     using storage_type = helpers::TypeHelperT<BYTE_COUNT * BYTE_WIDTH, false>;
61     using return_type = helpers::TypeHelperT<width, is_signed>;
62 
63     return ReadHelper<return_type, storage_type>(BYTE_OFFSET, BYTE_COUNT, offset, width);
64 }
65 
66 template <const BytecodeInstMode Mode>
67 // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_COMMENT_LOCATION)
68 template <bool is_signed /* = false */>
Read64(size_t offset,size_t width)69 inline auto BytecodeInst<Mode>::Read64(size_t offset, size_t width) const
70 {
71     constexpr size_t BIT64 = 64;
72     constexpr size_t BYTE_WIDTH = 8;
73 
74     ASSERT((offset % BYTE_WIDTH) + width <= BIT64);
75 
76     size_t byteoffset = offset / BYTE_WIDTH;
77     size_t byteoffset_end = (offset + width + BYTE_WIDTH - 1) / BYTE_WIDTH;
78     size_t bytecount = byteoffset_end - byteoffset;
79 
80     using storage_type = helpers::TypeHelperT<BIT64, false>;
81     using return_type = helpers::TypeHelperT<BIT64, is_signed>;
82 
83     return ReadHelper<return_type, storage_type>(byteoffset, bytecount, offset, width);
84 }
85 
86 template <const BytecodeInstMode Mode>
GetSize()87 inline size_t BytecodeInst<Mode>::GetSize() const
88 {
89     return Size(GetFormat());
90 }
91 
92 #include <bytecode_instruction-inl_gen.h>
93 
94 }  // namespace panda
95 
96 #endif  // PANDA_LIBPANDAFILE_BYTECODE_INSTRUCTION_INL_H_
97