Skip to content

Commit

Permalink
i#1569 AArch64: Implement move (immediate) to zero register. (#2423)
Browse files Browse the repository at this point in the history
Moving a value to the zero register is a no-op but we have seen
ADR XZR,... used by Node.js (libv8). Having these API functions,
instrlist_insert_mov_{immed_ptrsz,instr_addr}, create no instructions
potentially adds a case for the caller to handle but most uses of
those functions set the last two arguments to NULL in any case. If it
were a problem we could create a NOP instruction instead. Creating
actual moves to XZR seems less good and would be awkward if in
generating a constant value we ever used instructions that cannot
target XZR.
  • Loading branch information
egrimley-arm authored May 9, 2017
1 parent a77808f commit 42d0ebc
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 7 deletions.
24 changes: 17 additions & 7 deletions core/arch/aarchxx/mangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -1225,26 +1225,36 @@ insert_mov_immed_arch(dcontext_t *dcontext, instr_t *src_inst, byte *encode_esti
{
#ifdef AARCH64
instr_t *mov;
uint rt;
int i;

CLIENT_ASSERT(opnd_is_reg(dst),
"AArch64 cannot store an immediate direct to memory");
rt = opnd_get_reg(dst) - DR_REG_X0;
ASSERT(rt < 31);

if (opnd_get_reg(dst) == DR_REG_XZR) {
/* Moving a value to the zero register is a no-op. We insert nothing,
* so *first and *last are set to NULL. Caller beware!
*/
if (first != NULL)
*first = NULL;
if (last != NULL)
*last = NULL;
return;
}

ASSERT((uint)(opnd_get_reg(dst) - DR_REG_X0) < 31);
if (src_inst != NULL)
val = (ptr_int_t)encode_estimate;

/* movz x(rt), #(val & 0xffff) */
mov = INSTR_CREATE_movz(dcontext, opnd_create_reg(DR_REG_X0 + rt),
/* movz x(dst), #(val & 0xffff) */
mov = INSTR_CREATE_movz(dcontext, dst,
OPND_CREATE_INT16(val & 0xffff), OPND_CREATE_INT8(0));
PRE(ilist, instr, mov);
if (first != NULL)
*first = mov;
for (i = 1; i < 4; i++) {
if ((val >> (16 * i) & 0xffff) != 0) {
/* movk x(rt), #(val >> sh & 0xffff), lsl #(sh) */
mov = INSTR_CREATE_movk(dcontext, opnd_create_reg(DR_REG_X0 + rt),
/* movk x(dst), #(val >> sh & 0xffff), lsl #(sh) */
mov = INSTR_CREATE_movk(dcontext, dst,
OPND_CREATE_INT16((val >> 16 * i) & 0xffff),
OPND_CREATE_INT8(i * 16));
PRE(ilist, instr, mov);
Expand Down
4 changes: 4 additions & 0 deletions core/lib/instrument_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -5546,6 +5546,8 @@ DR_API
* Pointers to the first and last created meta instructions are returned
* in \p first and \p last, unless only one meta instruction is created,
* in which case NULL is returned in last.
* If the instruction is a no-op (when dst is the zero register on AArch64)
* then no instructions are created and NULL is returned in first and last.
*/
void
instrlist_insert_mov_immed_ptrsz(void *drcontext, ptr_int_t val, opnd_t dst,
Expand Down Expand Up @@ -5578,6 +5580,8 @@ DR_API
* Pointers to the first and last created meta instructions are returned
* in \p first and \p last, unless only one meta instruction is created,
* in which case NULL is returned in last.
* If the instruction is a no-op (when dst is the zero register on AArch64)
* then no instructions are created and NULL is returned in first and last.
*/
void
instrlist_insert_mov_instr_addr(void *drcontext, instr_t *src_inst,
Expand Down

0 comments on commit 42d0ebc

Please sign in to comment.