DexInstruction* DexInstruction::set_literal(int64_t literal) { assert(has_literal()); auto format = opcode_format(opcode()); switch (format) { case FMT_f11n: m_opcode = (m_opcode & 0xfff) | ((literal & 0xf) << 12); return this; case FMT_f21s: m_arg[0] = literal; return this; case FMT_f21h: m_arg[0] = literal >> 16; return this; case FMT_f22b: m_arg[0] = literal >> 48; return this; case FMT_f22s: m_arg[0] = literal; return this; case FMT_f31i: m_arg[0] = literal & 0xffff; m_arg[1] = literal >> 16; return this; case FMT_f51l: m_arg[0] = literal; m_arg[1] = literal >> 16; m_arg[2] = literal >> 32; m_arg[3] = literal >> 48; return this; default: assert(false); } not_reached(); }
void DexInstruction::verify_encoding() const { auto test = m_count ? new DexInstruction(opcode()) : new DexInstruction(opcode(), 0); if (dests_size()) { test->set_dest(dest()); } for (unsigned i = 0; i < srcs_size(); i++) { test->set_src(i, src(i)); } if (has_range_base()) test->set_range_base(range_base()); if (has_range_size()) test->set_range_size(range_size()); if (has_arg_word_count()) test->set_arg_word_count(arg_word_count()); if (has_literal()) test->set_literal(literal()); if (has_offset()) test->set_offset(offset()); assert_log(m_opcode == test->m_opcode, "%x %x\n", m_opcode, test->m_opcode); for (unsigned i = 0; i < m_count; i++) { assert_log(m_arg[i] == test->m_arg[i], "(%x %x) (%x %x)", m_opcode, m_arg[i], test->m_opcode, test->m_arg[i]); } delete test; }
int64_t DexInstruction::literal() const { assert(has_literal()); auto format = opcode_format(opcode()); switch (format) { case FMT_f11n: return signext<4>(m_opcode >> 12); case FMT_f21s: return signext<16>(m_arg[0]); case FMT_f21h: return signext<16>(m_arg[0]) << 16; case FMT_f22b: return signext<16>(m_arg[0]) << 48; case FMT_f22s: return signext<16>(m_arg[0]); case FMT_f31i: { auto literal = uint32_t(m_arg[0]) | (uint32_t(m_arg[1]) << 16); return signext<32>(literal); } case FMT_f51l: { auto literal = uint64_t(m_arg[0]) | (uint64_t(m_arg[1]) << 16) | (uint64_t(m_arg[2]) << 32) | (uint64_t(m_arg[3]) << 48); return signext<64>(literal); } default: assert(false); } not_reached(); }
static HSE_state ICACHE_FLASH_ATTR st_save_backlog(heatshrink_encoder *hse) { if (is_finishing(hse)) { /* copy remaining literal (if necessary) */ if (has_literal(hse)) { hse->flags |= FLAG_ON_FINAL_LITERAL; return HSES_YIELD_TAG_BIT; } else { return HSES_FLUSH_BITS; } } else { LOG("-- saving backlog\n"); save_backlog(hse); return HSES_NOT_FULL; } }
uint64_t IRInstruction::hash() const { std::vector<uint64_t> bits; bits.push_back(opcode()); for (size_t i = 0; i < srcs_size(); i++) { bits.push_back(src(i)); } if (dests_size() > 0) { bits.push_back(dest()); } if (has_data()) { size_t size = get_data()->data_size(); const auto& data = get_data()->data(); for (size_t i = 0; i < size; i++) { bits.push_back(data[i]); } } if (has_type()) { bits.push_back(reinterpret_cast<uint64_t>(get_type())); } if (has_field()) { bits.push_back(reinterpret_cast<uint64_t>(get_field())); } if (has_method()) { bits.push_back(reinterpret_cast<uint64_t>(get_method())); } if (has_string()) { bits.push_back(reinterpret_cast<uint64_t>(get_string())); } if (has_literal()) { bits.push_back(get_literal()); } uint64_t result = 0; for (uint64_t elem : bits) { result ^= elem; } return result; }