1/** 2 * Copyright (c) 2021-2022 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 LIBPANDAFILE_BYTECODE_INSTRUCTION_INL_H 17#define LIBPANDAFILE_BYTECODE_INSTRUCTION_INL_H 18 19#include "bytecode_instruction.h" 20#include "macros.h" 21 22namespace panda { 23 24template <const BytecodeInstMode Mode> 25template <class R, class S> 26inline 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 50template <const BytecodeInstMode Mode> 51template <size_t offset, size_t width, bool is_signed /* = false */> 52inline auto BytecodeInst<Mode>::Read() const 53{ 54 constexpr size_t BYTE_WIDTH = 8; 55 constexpr size_t BYTE_OFFSET = offset / BYTE_WIDTH; 56 constexpr size_t BYTE_OFFSET_END = (offset + width + BYTE_WIDTH - 1) / BYTE_WIDTH; 57 constexpr size_t BYTE_COUNT = BYTE_OFFSET_END - BYTE_OFFSET; 58 59 using storage_type = helpers::TypeHelperT<BYTE_COUNT * BYTE_WIDTH, false>; 60 using return_type = helpers::TypeHelperT<width, is_signed>; 61 62 return ReadHelper<return_type, storage_type>(BYTE_OFFSET, BYTE_COUNT, offset, width); 63} 64 65template <const BytecodeInstMode Mode> 66template <bool is_signed /* = false */> 67inline auto BytecodeInst<Mode>::Read64(size_t offset, size_t width) const 68{ 69 constexpr size_t BIT64 = 64; 70 constexpr size_t BYTE_WIDTH = 8; 71 72 ASSERT((offset % BYTE_WIDTH) + width <= BIT64); 73 74 size_t byteoffset = offset / BYTE_WIDTH; 75 size_t byteoffset_end = (offset + width + BYTE_WIDTH - 1) / BYTE_WIDTH; 76 size_t bytecount = byteoffset_end - byteoffset; 77 78 using storage_type = helpers::TypeHelperT<BIT64, false>; 79 using return_type = helpers::TypeHelperT<BIT64, is_signed>; 80 81 return ReadHelper<return_type, storage_type>(byteoffset, bytecount, offset, width); 82} 83 84template <const BytecodeInstMode Mode> 85inline size_t BytecodeInst<Mode>::GetSize() const 86{ 87 return Size(GetFormat()); 88} 89 90#include <bytecode_instruction-inl_gen.h> 91 92} // namespace panda 93 94#endif // LIBPANDAFILE_BYTECODE_INSTRUCTION_INL_H 95