static void instr_create_ldstex(dcontext_t *dcontext, int len, uint *pc, instr_t *instr, OUT instr_t *instr_ldstex) { int num_dsts = 0; int num_srcs = 0; int i, d, s, j; for (i = 0; i < len; i++) { ASSERT(instr[i].length == AARCH64_INSTR_SIZE && instr[i].bytes == instr[0].bytes + AARCH64_INSTR_SIZE * i); num_dsts += instr_num_dsts(&instr[i]); num_srcs += instr_num_srcs(&instr[i]); } instr_set_opcode(instr_ldstex, OP_ldstex); instr_set_num_opnds(dcontext, instr_ldstex, num_dsts, num_srcs); d = 0; s = 0; for (i = 0; i < len; i++) { int dsts = instr_num_dsts(&instr[i]); int srcs = instr_num_srcs(&instr[i]); for (j = 0; j < dsts; j++) instr_set_dst(instr_ldstex, d++, instr_get_dst(&instr[i], j)); for (j = 0; j < srcs; j++) instr_set_src(instr_ldstex, s++, instr_get_src(&instr[i], j)); } ASSERT(d == num_dsts && s == num_srcs); /* Set raw bits to original encoding. */ instr_set_raw_bits(instr_ldstex, instr[0].bytes, len * AARCH64_INSTR_SIZE); /* Conservatively assume all flags are read and written. */ instr_ldstex->eflags = EFLAGS_READ_ALL | EFLAGS_WRITE_ALL; instr_set_eflags_valid(instr_ldstex, true); }
static inline void instr_set_1dst_0src(dcontext_t *dc, instr_t *instr, int op, opnd_t dst0) { instr_set_opcode(instr, op); instr_set_num_opnds(dc, instr, 1, 0); instr_set_dst(instr, 0, dst0); }
static inline void instr_set_1dst_2src(dcontext_t *dc, instr_t *instr, int op, opnd_t dst0, opnd_t src0, opnd_t src1) { instr_set_opcode(instr, op); instr_set_num_opnds(dc, instr, 1, 2); instr_set_dst(instr, 0, dst0); instr_set_src(instr, 0, src0); instr_set_src(instr, 1, src1); }
void modify_instr_for_relocations(void *drcontext, instr_t *inst, ptr_uint_t *immed, ptr_uint_t *disp) { int i; ptr_uint_t limmed = 0, ldisp = 0; for (i = instr_num_srcs(inst) - 1; i >= 0; i--) { opnd_t opnd = instr_get_src(inst, i); if (opnd_is_immed_int(opnd) && opnd_get_immed_int(opnd) > 0x10000) { if (limmed != 0) { ASSERT(false); } else { limmed = opnd_get_immed_int(opnd); } instr_set_src(inst, i, opnd_create_immed_int(0, opnd_get_size(opnd))); } if (opnd_is_base_disp(opnd) && opnd_get_disp(opnd) > 0x10000) { if (ldisp != 0 && ldisp != opnd_get_disp(opnd)) { ASSERT(false); } else { ldisp = opnd_get_disp(opnd); } instr_set_src(inst, i, opnd_create_base_disp(opnd_get_base(opnd), opnd_get_index(opnd), opnd_get_scale(opnd), 0, opnd_get_size(opnd))); } } for (i = instr_num_dsts(inst) - 1; i >= 0; i--) { opnd_t opnd = instr_get_dst(inst, i); ASSERT(!opnd_is_immed(opnd)); if (opnd_is_base_disp(opnd) && opnd_get_disp(opnd) > 0x10000) { if (ldisp != 0 && ldisp != opnd_get_disp(opnd)) { ASSERT(false); } else { ldisp = opnd_get_disp(opnd); } instr_set_dst(inst, i, opnd_create_base_disp(opnd_get_base(opnd), opnd_get_index(opnd), opnd_get_scale(opnd), 0, opnd_get_size(opnd))); } } if (limmed != 0) *immed = limmed; if (ldisp != 0) *disp = ldisp; }