bool instr_is_mov_constant(instr_t *instr, ptr_int_t *value) { int opc = instr_get_opcode(instr); if (opc == OP_eor) { /* We include OP_eor for symmetry w/ x86, but on ARM "mov reg, #0" is * just as compact and there's no reason to use an xor. */ if (opnd_same(instr_get_src(instr, 0), instr_get_dst(instr, 0)) && opnd_same(instr_get_src(instr, 0), instr_get_src(instr, 1)) && /* Must be the form with "sh2, i5_7" and no shift */ instr_num_srcs(instr) == 4 && opnd_get_immed_int(instr_get_src(instr, 2)) == DR_SHIFT_NONE && opnd_get_immed_int(instr_get_src(instr, 3)) == 0) { *value = 0; return true; } else return false; } else if (opc == OP_mvn || opc == OP_mvns) { opnd_t op = instr_get_src(instr, 0); if (opnd_is_immed_int(op)) { *value = -opnd_get_immed_int(op); return true; } else return false; } else if (opc == OP_mov || opc == OP_movs || opc == OP_movw) { opnd_t op = instr_get_src(instr, 0); if (opnd_is_immed_int(op)) { *value = opnd_get_immed_int(op); return true; } else return false; } return false; }
static bool instr_is_reg_restore(instr_t *instr, reg_id_t reg, umbra_info_t *info) { opnd_t opnd; int slot; if (instr_get_opcode(instr) != OP_mov_ld) return false; opnd = instr_get_dst(instr, 0); if (!opnd_is_reg(opnd) || opnd_get_reg(opnd) != reg) return false; slot = reg - REG_SPILL_START; opnd = OPND_CREATE_ABSMEM(&info->spill_regs[slot], OPSZ_PTR); if (opnd_same(opnd, instr_get_src(instr, 0))) return true; return false; }
static bool reg_update_is_limited(instr_t *instr, reg_id_t reg) { int opcode; int offset; opcode = instr_get_opcode(instr); if (opcode == OP_inc || opcode == OP_dec) return true; if (opcode == OP_and) /* for 0xffffffd0 & reg => reg */ return true; if ((opcode == OP_add || opcode == OP_sub || opcode == OP_adc || opcode == OP_sbb) && opnd_is_immed_int(instr_get_src(instr, 0))) { offset = opnd_get_immed_int(instr_get_src(instr, 0)); if (offset > PAGE_SIZE || offset < -PAGE_SIZE) return false; return true; } if (reg != DR_REG_XSP) return false; if (opcode >= OP_push && opcode <= OP_popa) { if (opcode == OP_pop && opnd_same(instr_get_dst(instr, 0), opnd_create_reg(DR_REG_XSP))) return false; return true; } if (opcode >= OP_call && opcode <= OP_call_far_ind) return true; if (opcode == OP_ret || opcode == OP_ret_far || opcode == OP_enter || opcode == OP_leave || opcode == OP_pushf || opcode == OP_popf) return true; return false; }