MethodBlock* MethodBlock::if_test(DexOpcode if_op, Location first, Location second) { always_assert(OPCODE_IF_EQ <= if_op && if_op <= OPCODE_IF_LE); DexInstruction* op = new DexInstruction(if_op); op->set_src(0, reg_num(first)); op->set_src(1, reg_num(second)); return make_if_block(op); }
MethodBlock* MethodBlock::if_else_test(DexCodeItemOpcode if_op, Location first, Location second, MethodBlock** true_block) { always_assert(OPCODE_IF_EQ <= if_op && if_op <= OPCODE_IF_LE); DexOpcode* op = new DexOpcode(if_op); op->set_src(0, reg_num(first)); op->set_src(1, reg_num(second)); return make_if_else_block(op, true_block); }
void MethodBlock::binop_2addr(DexOpcode op, const Location& dest, const Location& src) { always_assert(OPCODE_ADD_INT_2ADDR <= op && op <= OPCODE_REM_DOUBLE_2ADDR); always_assert(dest.type == src.type); DexInstruction* insn = new DexInstruction(op); insn->set_src(0, reg_num(dest)); insn->set_src(1, reg_num(src)); push_instruction(insn); }
void MethodBlock::sfield_op(DexOpcode opcode, DexField* field, Location& src_or_dst) { always_assert(is_sfield_op(opcode)); if (is_sget(opcode)) { auto sget = new DexOpcodeField(opcode, field); sget->set_dest(reg_num(src_or_dst)); src_or_dst.type = field->get_class(); push_instruction(sget); } else { auto sput = new DexOpcodeField(opcode, field); sput->set_src(0, reg_num(src_or_dst)); push_instruction(sput); } }
void MethodBlock::load_const(Location& loc, DexString* value) { always_assert(!loc.is_wide()); DexInstruction* load = new DexOpcodeString(OPCODE_CONST_STRING, value); load->set_dest(reg_num(loc)); loc.type = get_string_type(); push_instruction(load); }
void MethodBlock::load_const(Location& loc, DexType* value) { always_assert(!loc.is_wide()); DexInstruction* load = new DexOpcodeType(OPCODE_CONST_CLASS, value); load->set_dest(reg_num(loc)); loc.type = get_class_type(); push_instruction(load); }
MethodBlock* MethodBlock::if_else_testz(DexOpcode if_op, Location test, MethodBlock** true_block) { always_assert(OPCODE_IF_EQZ <= if_op && if_op <= OPCODE_IF_LEZ); DexInstruction* op = new DexInstruction(if_op); op->set_src(0, reg_num(test)); return make_if_else_block(op, true_block); }
void MethodBlock::load_const(Location& loc, int32_t value) { always_assert(!loc.is_wide()); DexOpcode* load = new DexOpcode(OPCODE_CONST_16); load->set_dest(reg_num(loc)); load->set_literal(value); loc.type = get_int_type(); push_opcode(load); }
void MethodBlock::load_null(Location& loc) { always_assert(!loc.is_wide()); DexInstruction* load = new DexInstruction(OPCODE_CONST_4); load->set_dest(reg_num(loc)); load->set_literal(0); loc.type = get_object_type(); push_instruction(load); }
void MethodBlock::load_const(Location& loc, double value) { always_assert(loc.is_wide()); DexInstruction* load = new DexInstruction(OPCODE_CONST_WIDE); load->set_dest(reg_num(loc)); load->set_literal(value); loc.type = get_double_type(); push_instruction(load); }
void MethodBlock::move(Location src, Location& dst) { always_assert(src.is_compatible(dst.type)); auto ch = type_shorty(dst.type); assert(ch != 'V'); DexOpcode opcode; if (ch == 'L') opcode = OPCODE_MOVE_OBJECT; else if (ch == 'J' || ch == 'D') opcode = OPCODE_MOVE_WIDE; else opcode = OPCODE_MOVE; DexInstruction* move = new DexInstruction(opcode); move->set_dest(reg_num(dst)); move->set_src(0, reg_num(src)); dst.type = src.type; push_instruction(move); }
void MethodBlock::ifield_op(DexCodeItemOpcode opcode, DexField* field, Location obj, Location& src_or_dst) { always_assert(is_ifield_op(opcode)); if (is_iget(opcode)) { auto iget = new DexOpcodeField(opcode, field); iget->set_dest(reg_num(src_or_dst)); src_or_dst.type = field->get_class(); iget->set_src(0, reg_num(obj)); push_opcode(iget); } else { auto iput = new DexOpcodeField(opcode, field); iput->set_src(0, reg_num(src_or_dst)); iput->set_src(1, reg_num(obj)); push_opcode(iput); } }
void MethodBlock::invoke(DexOpcode opcode, DexMethod* meth, std::vector<Location>& args) { always_assert(is_invoke(opcode)); auto invk = new DexOpcodeMethod(opcode, meth, 0); uint16_t arg_count = static_cast<uint16_t>(args.size()); invk->set_arg_word_count(arg_count); for (uint16_t i = 0; i < arg_count; i++) { auto arg = args[i]; invk->set_src(i, reg_num(arg)); } if (arg_count > mc->out_count) mc->out_count = arg_count; push_instruction(invk); }
void MethodBlock::ret(Location loc) { auto ch = type_shorty(loc.type); assert(ch != 'V'); DexOpcode opcode; if (ch == 'L') opcode = OPCODE_RETURN_OBJECT; else if (ch == 'J' || ch == 'D') opcode = OPCODE_RETURN_WIDE; else opcode = OPCODE_RETURN; auto ret = new DexInstruction(opcode); ret->set_src(0, reg_num(loc)); push_instruction(ret); }
void MethodBlock::move_result(Location& dst, DexType* type) { always_assert(dst.is_compatible(type)); auto ch = type_shorty(type); assert(ch != 'V'); DexOpcode opcode; if (ch == 'L') opcode = OPCODE_MOVE_RESULT_OBJECT; else if (ch == 'J' || ch == 'D') opcode = OPCODE_MOVE_RESULT_WIDE; else opcode = OPCODE_MOVE_RESULT; DexInstruction* mov_res = new DexInstruction(opcode); mov_res->set_dest(reg_num(dst)); dst.type = type; push_instruction(mov_res); }
int32_t aarch64_get_reg_s16 (sim_cpu *cpu, GReg reg, int r31_is_sp) { return cpu->gr[reg_num(reg)].s16; }
uint32_t aarch64_get_reg_u32 (sim_cpu *cpu, GReg reg, int r31_is_sp) { return cpu->gr[reg_num(reg)].u32; }
int64_t aarch64_get_reg_s64 (sim_cpu *cpu, GReg reg, int r31_is_sp) { return cpu->gr[reg_num(reg)].s64; }
MethodBlock* MethodBlock::switch_op(Location test, std::map<int, MethodBlock*>& cases) { auto sw_opcode = new DexInstruction(OPCODE_PACKED_SWITCH); sw_opcode->set_src(0, reg_num(test)); return make_switch_block(sw_opcode, cases); }
MethodBlock* MethodBlock::if_testz(DexCodeItemOpcode if_op, Location test) { always_assert(OPCODE_IF_EQZ <= if_op && if_op <= OPCODE_IF_LEZ); DexOpcode* op = new DexOpcode(if_op); op->set_src(0, reg_num(test)); return make_if_block(op); }