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