Skip to content

Commit

Permalink
i#1569 AArch64: Implement some simple functions required by clients.
Browse files Browse the repository at this point in the history
Implement functions in decode.c, emit_utils.c, instr.c, proc.c,
mangle.c, opnd.c, instr_shared.c, opnd_shared.c, instrument.c.

Review-URL: https://codereview.appspot.com/303990043
  • Loading branch information
Kevin Zhou authored and egrimley-arm committed Jul 19, 2016
1 parent 1836b86 commit 6279847
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 49 deletions.
9 changes: 3 additions & 6 deletions core/arch/aarch64/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,14 @@ DR_API
app_pc
dr_app_pc_as_jump_target(dr_isa_mode_t isa_mode, app_pc pc)
{
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
return 0;
return pc;
}

DR_API
app_pc
dr_app_pc_as_load_target(dr_isa_mode_t isa_mode, app_pc pc)
{
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
return 0;
return pc;
}

byte *
Expand Down Expand Up @@ -171,8 +169,7 @@ DR_API
const char *
decode_opcode_name(int opcode)
{
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
return NULL;
return get_opcode_name(opcode);
}

opnd_size_t
Expand Down
28 changes: 27 additions & 1 deletion core/arch/aarch64/emit_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,33 @@ relink_special_ibl_xfer(dcontext_t *dcontext, int index,
ibl_entry_point_type_t entry_type,
ibl_branch_type_t ibl_type)
{
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
generated_code_t *code;
byte *ibl_tgt;
uint *pc;
if (dcontext == GLOBAL_DCONTEXT) {
ASSERT(!special_ibl_xfer_is_thread_private()); /* else shouldn't be called */
code = SHARED_GENCODE_MATCH_THREAD(get_thread_private_dcontext());
} else {
ASSERT(special_ibl_xfer_is_thread_private()); /* else shouldn't be called */
code = THREAD_GENCODE(dcontext);
}
if (code == NULL) /* thread private that we don't need */
return;
ibl_tgt = special_ibl_xfer_tgt(dcontext, code, entry_type, ibl_type);
ASSERT(code->special_ibl_xfer[index] != NULL);
pc = (uint *)(code->special_ibl_xfer[index] + code->special_ibl_unlink_offs[index]);

protect_generated_code(code, WRITABLE);

/* ldr x1, [x(stolen), #(offs)] */
pc[0] = (0xf9400000 | 1 | (dr_reg_stolen - DR_REG_X0) << 5 |
get_ibl_entry_tls_offs(dcontext, ibl_tgt) >> 3 << 10);

/* br x1 */
pc[1] = 0xd61f0000 | 1 << 5;

machine_cache_sync(pc, pc + 2, true);
protect_generated_code(code, READONLY);
}

bool
Expand Down
53 changes: 46 additions & 7 deletions core/arch/aarch64/instr.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,13 +208,44 @@ instr_is_syscall(instr_t *instr)
bool
instr_is_mov_constant(instr_t *instr, ptr_int_t *value)
{
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
uint opc = instr_get_opcode(instr);

/* We include several instructions that an assembler might generate for
* "MOV reg, #imm", but not EOR or SUB or other instructions that could
* in theory be used to generate a zero, nor "MOV reg, wzr/xzr" (for now).
*/

/* movn/movz reg, imm */
/* FIXME i#1569: NYI */
if (false) {
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;
}

/* orr/add/sub reg, xwr/xzr, imm */
if (opc == OP_orr || opc == OP_add || opc == OP_sub) {
opnd_t reg = instr_get_src(instr, 0);
opnd_t imm = instr_get_src(instr, 1);
if (opnd_is_reg(reg) &&
(opnd_get_reg(reg) == DR_REG_WZR ||
opnd_get_reg(reg) == DR_REG_XZR) &&
opnd_is_immed_int(imm)) {
*value = opnd_get_immed_int(imm);
return true;
} else
return false;
}

return false;
}

bool instr_is_prefetch(instr_t *instr)
{
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
/* FIXME i#1569: NYI */
return false;
}

Expand All @@ -227,7 +258,15 @@ instr_saves_float_pc(instr_t *instr)
bool
instr_is_undefined(instr_t *instr)
{
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
/* FIXME i#1569: Without a complete decoder we cannot recognise all
* unallocated encodings, but for testing purposes we can recognise
* some of them: blocks at the top and bottom of the encoding space.
*/
if (instr_opcode_valid(instr) &&
instr_get_opcode(instr) == OP_xx) {
uint enc = opnd_get_immed_int(instr_get_src(instr, 0));
return ((enc & 0x18000000) == 0 || (~enc & 0xde000000) == 0);
}
return false;
}

Expand Down Expand Up @@ -296,10 +335,10 @@ reg_is_fp(reg_id_t reg)
}

bool
instr_is_nop(instr_t *inst)
instr_is_nop(instr_t *instr)
{
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
return false;
uint opc = instr_get_opcode(instr);
return (opc == OP_nop);
}

bool
Expand Down Expand Up @@ -336,6 +375,6 @@ DR_API
bool
instr_is_exclusive_store(instr_t *instr)
{
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
/* FIXME i#1569: NYI */
return false;
}
24 changes: 21 additions & 3 deletions core/arch/aarch64/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,33 @@ DR_API
size_t
proc_save_fpstate(byte *buf)
{
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
return 0;
__asm__ __volatile__
("st1 {v0.2d-v3.2d}, [%0], #64\n\t"
"st1 {v4.2d-v7.2d}, [%0], #64\n\t"
"st1 {v8.2d-v11.2d}, [%0], #64\n\t"
"st1 {v12.2d-v15.2d}, [%0], #64\n\t"
"st1 {v16.2d-v19.2d}, [%0], #64\n\t"
"st1 {v20.2d-v23.2d}, [%0], #64\n\t"
"st1 {v24.2d-v27.2d}, [%0], #64\n\t"
"st1 {v28.2d-v31.2d}, [%0], #64\n\t"
: "=r"(buf) : "r"(buf) : "memory");
return DR_FPSTATE_BUF_SIZE;
}

DR_API
void
proc_restore_fpstate(byte *buf)
{
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
__asm__ __volatile__
("ld1 {v0.2d-v3.2d}, [%0], #64\n\t"
"ld1 {v4.2d-v7.2d}, [%0], #64\n\t"
"ld1 {v8.2d-v11.2d}, [%0], #64\n\t"
"ld1 {v12.2d-v15.2d}, [%0], #64\n\t"
"ld1 {v16.2d-v19.2d}, [%0], #64\n\t"
"ld1 {v20.2d-v23.2d}, [%0], #64\n\t"
"ld1 {v24.2d-v27.2d}, [%0], #64\n\t"
"ld1 {v28.2d-v31.2d}, [%0], #64\n\t"
: "=r"(buf) : "r"(buf) : "memory");
}

void
Expand Down
22 changes: 14 additions & 8 deletions core/arch/aarchxx/mangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -842,14 +842,16 @@ void
insert_mov_immed_arch(dcontext_t *dcontext, instr_t *src_inst, byte *encode_estimate,
ptr_int_t val, opnd_t dst,
instrlist_t *ilist, instr_t *instr,
instr_t **first, instr_t **second)
OUT instr_t **first, OUT instr_t **second)
{
#ifdef AARCH64
/* XXX: Generates MOVZ and some MOVKs. It could easily be improved. */
/* FIXME i#1977: AArch64 may generate more than two instructions.
* We set "second" to point at the last emitted instruction.
*/
instr_t *mov;
uint rt;
int i;

ASSERT(first == NULL && second == NULL);
CLIENT_ASSERT(opnd_is_reg(dst),
"AArch64 cannot store an immediate direct to memory");
rt = opnd_get_reg(dst) - DR_REG_X0;
Expand All @@ -858,16 +860,20 @@ insert_mov_immed_arch(dcontext_t *dcontext, instr_t *src_inst, byte *encode_esti
val = (ptr_int_t)encode_estimate;

/* movz x(rt), #(val & 0xffff) */
PRE(ilist, instr, INSTR_CREATE_xx(dcontext, 0xd2800000 |
rt | (val & 0xffff) << 5));
mov = INSTR_CREATE_xx(dcontext, 0xd2800000 | rt | (val & 0xffff) << 5);
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) */
PRE(ilist, instr, INSTR_CREATE_xx(dcontext, 0xf2800000 | rt |
((val >> 16 * i) & 0xffff) << 5 |
i << 21));
mov = INSTR_CREATE_xx(dcontext, 0xf2800000 | rt |
((val >> 16 * i) & 0xffff) << 5 | i << 21);
PRE(ilist, instr, mov);
}
}
if (second != NULL)
*second = mov;
#else
instr_t *mov1, *mov2;
if (src_inst != NULL)
Expand Down
13 changes: 6 additions & 7 deletions core/arch/aarchxx/opnd.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,21 @@ DR_API
bool
reg_is_stolen(reg_id_t reg)
{
#ifdef AARCH64
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
return false;
#else
if (dr_reg_fixer[reg] == dr_reg_stolen && dr_reg_fixer[reg] != DR_REG_NULL)
return true;
return false;
#endif
}

int
opnd_get_reg_dcontext_offs(reg_id_t reg)
{
#ifdef AARCH64
if (DR_REG_R0 <= reg && reg <= DR_REG_R30)
return R0_OFFSET + (R1_OFFSET - R0_OFFSET) * (reg - DR_REG_R0);
if (DR_REG_X0 <= reg && reg <= DR_REG_X30)
return R0_OFFSET + (R1_OFFSET - R0_OFFSET) * (reg - DR_REG_X0);
if (DR_REG_W0 <= reg && reg <= DR_REG_W30)
return R0_OFFSET + (R1_OFFSET - R0_OFFSET) * (reg - DR_REG_W0);
if (reg == DR_REG_XSP || reg == DR_REG_WSP)
return XSP_OFFSET;
CLIENT_ASSERT(false, "opnd_get_reg_dcontext_offs: invalid reg");
return -1;
#else
Expand Down
4 changes: 2 additions & 2 deletions core/arch/instr_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -3034,8 +3034,8 @@ instr_create_save_immedN_to_dcontext(dcontext_t *dcontext, opnd_size_t sz,
opnd_t memopnd = opnd_create_dcontext_field_sz(dcontext, offs, sz);
/* PR 244737: thread-private scratch space needs to fixed for x64 */
IF_X64(ASSERT_NOT_IMPLEMENTED(false));
/* there is no immed to mem instr on ARM */
IF_ARM(ASSERT_NOT_IMPLEMENTED(false));
/* There is no immed to mem instr on ARM/AArch64. */
IF_AARCHXX(ASSERT_NOT_IMPLEMENTED(false));
return XINST_CREATE_store(dcontext, memopnd, immed_op);
}

Expand Down
11 changes: 5 additions & 6 deletions core/arch/opnd_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -1789,17 +1789,15 @@ opnd_compute_address_priv(opnd_t opnd, priv_mcontext_t *mc)
#ifdef X86
ptr_int_t scale = opnd_get_scale(opnd);
scaled_index = scale * reg_get_value_priv(index, mc);
#elif defined(AARCH64)
(void)index;
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
#elif defined(ARM)
#elif defined(AARCHXX)
uint amount;
dr_shift_type_t type = opnd_get_index_shift(opnd, &amount);
reg_t index_val = reg_get_value_priv(index, mc);
switch (type) {
case DR_SHIFT_LSL:
scaled_index = index_val << amount;
break;
# ifndef AARCH64
case DR_SHIFT_LSR:
scaled_index = index_val >> amount;
break;
Expand All @@ -1814,6 +1812,7 @@ opnd_compute_address_priv(opnd_t opnd, priv_mcontext_t *mc)
scaled_index = (index_val >> 1) ||
(TEST(EFLAGS_C, mc->cpsr) ? (1 << (sizeof(reg_t)*8-1)) : 0);
break;
# endif
default:
scaled_index = index_val;
}
Expand Down Expand Up @@ -1925,9 +1924,9 @@ reg_32_to_opsz(reg_id_t reg, opnd_size_t sz)
if (sz == OPSZ_4)
return reg;
else if (sz == OPSZ_2)
return IF_ARM_ELSE(reg, reg_32_to_16(reg));
return IF_AARCHXX_ELSE(reg, reg_32_to_16(reg));
else if (sz == OPSZ_1)
return IF_ARM_ELSE(reg, reg_32_to_8(reg));
return IF_AARCHXX_ELSE(reg, reg_32_to_8(reg));
#ifdef X64
else if (sz == OPSZ_8)
return reg_32_to_64(reg);
Expand Down
23 changes: 14 additions & 9 deletions core/lib/instrument.c
Original file line number Diff line number Diff line change
Expand Up @@ -4522,7 +4522,7 @@ dr_set_tls_field(void *drcontext, void *value)
DR_API void *
dr_get_dr_segment_base(IN reg_id_t seg)
{
#ifdef ARM
#ifdef AARCHXX
if (seg == dr_reg_stolen)
return os_get_dr_tls_base(get_thread_private_dcontext());
else
Expand Down Expand Up @@ -5649,9 +5649,12 @@ dr_save_arith_flags_to_reg(void *drcontext, instrlist_t *ilist,
opnd_create_reg(reg),
opnd_create_reg(DR_REG_CPSR)));
#elif defined(AARCH64)
(void)dcontext;
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
#endif /* X86/ARM */
/* flag saving code: mrs reg, nzcv */
MINSERT(ilist, where,
INSTR_CREATE_mrs(dcontext,
opnd_create_reg(reg),
opnd_create_reg(DR_REG_NZCV)));
#endif /* X86/ARM/AARCH64 */
}

DR_API void
Expand Down Expand Up @@ -5684,9 +5687,11 @@ dr_restore_arith_flags_from_reg(void *drcontext, instrlist_t *ilist,
opnd_create_reg(reg)));
#elif defined(AARCH64)
/* flag restoring code: mrs reg, nzcv */
(void)dcontext;
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
#endif /* X86/ARM */
MINSERT(ilist, where,
INSTR_CREATE_msr(dcontext,
opnd_create_reg(DR_REG_NZCV),
opnd_create_reg(reg)));
#endif /* X86/ARM/AARCH64 */
}

/* providing functionality of old -instr_calls and -instr_branches flags
Expand Down Expand Up @@ -7151,7 +7156,7 @@ dr_insert_get_stolen_reg_value(void *drcontext, instrlist_t *ilist,
"dr_insert_get_stolen_reg: reg has wrong size\n");
CLIENT_ASSERT(!reg_is_stolen(reg),
"dr_insert_get_stolen_reg: reg is used by DynamoRIO\n");
#ifdef ARM
#ifdef AARCHXX
instrlist_meta_preinsert
(ilist, instr,
instr_create_restore_from_tls(drcontext, reg, TLS_REG_STOLEN_SLOT));
Expand All @@ -7169,7 +7174,7 @@ dr_insert_set_stolen_reg_value(void *drcontext, instrlist_t *ilist,
"dr_insert_set_stolen_reg: reg has wrong size\n");
CLIENT_ASSERT(!reg_is_stolen(reg),
"dr_insert_set_stolen_reg: reg is used by DynamoRIO\n");
#ifdef ARM
#ifdef AARCHXX
instrlist_meta_preinsert
(ilist, instr,
instr_create_save_to_tls(drcontext, reg, TLS_REG_STOLEN_SLOT));
Expand Down

0 comments on commit 6279847

Please sign in to comment.