Skip to content

Commit

Permalink
i#1569 AArch64: Add macro to create ADR and ADRP instructions. (#2317)
Browse files Browse the repository at this point in the history
Also adds support for instruction operands to ADR and ADRP encoders.
  • Loading branch information
fhahn authored Apr 7, 2017
1 parent 89073de commit 428b896
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 16 deletions.
28 changes: 18 additions & 10 deletions core/arch/aarch64/codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,15 +430,21 @@ decode_opnd_adr_page(int scale, uint enc, byte *pc, OUT opnd_t *opnd)
}

static bool
encode_opnd_adr_page(int scale, byte *pc, opnd_t opnd, OUT uint *enc_out)
encode_opnd_adr_page(int scale, byte *pc, opnd_t opnd, OUT uint *enc_out,
instr_t *instr)
{
void *addr;
ptr_int_t offset;
uint bits;
if (!opnd_is_rel_addr(opnd))
if (opnd_is_rel_addr(opnd)) {
offset = (ptr_int_t)opnd_get_addr(opnd) -
(ptr_int_t)((ptr_uint_t)pc >> scale << scale);
} else if (opnd_is_instr(opnd)) {
offset = (ptr_int_t)
((byte *)opnd_get_instr(opnd)->note - (byte *)instr->note);
} else
return false;
addr = opnd_get_addr(opnd);
if (!try_encode_int(&bits, 21, scale,
(ptr_int_t)addr - (ptr_int_t)((ptr_uint_t)pc >> scale << scale)))

if (!try_encode_int(&bits, 21, scale, offset))
return false;
*enc_out = (bits & 3) << 29 | (bits & 0x1ffffc) << 3;
return true;
Expand Down Expand Up @@ -845,9 +851,10 @@ decode_opnd_adr(uint enc, int opcode, byte *pc, OUT opnd_t *opnd)
}

static inline bool
encode_opnd_adr(uint enc, int opcode, byte *pc, opnd_t opnd, OUT uint *enc_out)
encode_opnd_adr(uint enc, int opcode, byte *pc, opnd_t opnd, OUT uint *enc_out,
instr_t *instr)
{
return encode_opnd_adr_page(0, pc, opnd, enc_out);
return encode_opnd_adr_page(0, pc, opnd, enc_out, instr);
}

/* adrp: operand of ADRP */
Expand All @@ -859,9 +866,10 @@ decode_opnd_adrp(uint enc, int opcode, byte *pc, OUT opnd_t *opnd)
}

static inline bool
encode_opnd_adrp(uint enc, int opcode, byte *pc, opnd_t opnd, OUT uint *enc_out)
encode_opnd_adrp(uint enc, int opcode, byte *pc, opnd_t opnd, OUT uint *enc_out,
instr_t *instr)
{
return encode_opnd_adr_page(12, pc, opnd, enc_out);
return encode_opnd_adr_page(12, pc, opnd, enc_out, instr);
}

/* b0: B register at bit position 0 */
Expand Down
16 changes: 12 additions & 4 deletions core/arch/aarch64/codec.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,14 @@ def gen(c, pats, depth):
c.append('}')
return '\n'.join(c) + '\n'


def maybe_instr(opnd):
if opnd in ('adr', 'adrp'):
return ', instr'
else:
return ''


def generate_encoder(patterns, opndsgen, opndtypes):
c = []
for name in sorted(opndsgen):
Expand All @@ -144,11 +152,11 @@ def generate_encoder(patterns, opndsgen, opndtypes):
tests = (['instr_num_dsts(instr) == %d && instr_num_srcs(instr) == %d' %
(len(dsts), len(srcs))] +
['encode_opnd_%s(enc & 0x%08x, opcode, '
'pc, instr_get_dst(instr, %d), &dst%d)' %
(dsts[i], f | opndtypes[dsts[i]], i, i) for i in range(len(dsts))] +
'pc, instr_get_dst(instr, %d), &dst%d%s)' %
(dsts[i], f | opndtypes[dsts[i]], i, i, maybe_instr(dsts[i])) for i in range(len(dsts))] +
['encode_opnd_%s(enc & 0x%08x, opcode, '
'pc, instr_get_src(instr, %d), &src%d)' %
(srcs[i], f | opndtypes[srcs[i]], i, i) for i in range(len(srcs))])
'pc, instr_get_src(instr, %d), &src%d%s)' %
(srcs[i], f | opndtypes[srcs[i]], i, i, maybe_instr(srcs[i])) for i in range(len(srcs))])
tests2 = (['dst%d == (enc & 0x%08x)' % (i, opndtypes[dsts[i]])
for i in range(len(dsts))] +
['src%d == (enc & 0x%08x)' % (i, opndtypes[srcs[i]])
Expand Down
2 changes: 2 additions & 0 deletions core/arch/aarch64/codec.txt
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ x---------------------xxxxx----- wx5sp # W/X register or WSP/XSP
x----------------xxxxx---------- wx10 # W/X register (or WZR/XZR)
x----------xxxxx---------------- wx16 # W/X register (or WZR/XZR)

# Note: The encoders for adr and adrp take the current instruction as argument
# in order to support calculating offsets for instruction operands.
################################################################################
# Instruction patterns

Expand Down
4 changes: 2 additions & 2 deletions core/arch/aarch64/encode_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -2959,7 +2959,7 @@ encode_opndsgen_10000000(byte *pc, instr_t *instr, uint enc)
uint dst0, src0;
if (instr_num_dsts(instr) == 1 && instr_num_srcs(instr) == 1 &&
encode_opnd_x0(enc & 0x9f00001f, opcode, pc, instr_get_dst(instr, 0), &dst0) &&
encode_opnd_adr(enc & 0xffffffe0, opcode, pc, instr_get_src(instr, 0), &src0)) {
encode_opnd_adr(enc & 0xffffffe0, opcode, pc, instr_get_src(instr, 0), &src0, instr)) {
ASSERT((dst0 & 0xffffffe0) == 0);
ASSERT((src0 & 0x9f00001f) == 0);
enc |= dst0 | src0;
Expand Down Expand Up @@ -5077,7 +5077,7 @@ encode_opndsgen_90000000(byte *pc, instr_t *instr, uint enc)
uint dst0, src0;
if (instr_num_dsts(instr) == 1 && instr_num_srcs(instr) == 1 &&
encode_opnd_x0(enc & 0x9f00001f, opcode, pc, instr_get_dst(instr, 0), &dst0) &&
encode_opnd_adrp(enc & 0xffffffe0, opcode, pc, instr_get_src(instr, 0), &src0)) {
encode_opnd_adrp(enc & 0xffffffe0, opcode, pc, instr_get_src(instr, 0), &src0, instr)) {
ASSERT((dst0 & 0xffffffe0) == 0);
ASSERT((src0 & 0x9f00001f) == 0);
enc |= dst0 | src0;
Expand Down
4 changes: 4 additions & 0 deletions core/arch/aarch64/instr_create.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,10 @@
instr_create_1dst_4src((dc), OP_sub, (rd), (rn), (rm_or_imm), (sht), (sha))
#define INSTR_CREATE_svc(dc, imm) \
instr_create_0dst_1src((dc), OP_svc, (imm))
#define INSTR_CREATE_adr(dc, rt, imm) \
instr_create_1dst_1src(dc, OP_adr, rt, imm)
#define INSTR_CREATE_adrp(dc, rt, imm) \
instr_create_1dst_1src(dc, OP_adrp, rt, imm)

/* FIXME i#1569: these two should perhaps not be provided */
#define INSTR_CREATE_add_shimm(dc, rd, rn, rm_or_imm, sht, sha) \
Expand Down

0 comments on commit 428b896

Please sign in to comment.