Skip to content

Commit

Permalink
i#1569 AArch64: Add support for implicit X30 operands for BL and BLR. (
Browse files Browse the repository at this point in the history
#2345)

The BL and BLR instruction store the return address in X30, This patch
adds X30 as (implicit) destination register for BL and BLR.
  • Loading branch information
fhahn authored Apr 19, 2017
1 parent 9da55c6 commit 3275b81
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 12 deletions.
28 changes: 26 additions & 2 deletions core/arch/aarch64/codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,24 @@ encode_opnd_imms(uint enc, int opcode, byte *pc, opnd_t opnd, OUT uint *enc_out)
return encode_opnd_imm_bf(10, enc, opnd, enc_out);
}

/* impx30: implicit X30 operand, used by BLR. */

static inline bool
decode_opnd_impx30(uint enc, int opcode, byte *pc, OUT opnd_t *opnd)
{
*opnd = opnd_create_reg(DR_REG_X30);
return true;
}

static inline bool
encode_opnd_impx30(uint enc, int opcode, byte *pc, opnd_t opnd, OUT uint *enc_out)
{
if (!opnd_is_reg(opnd) || opnd_get_reg(opnd) != DR_REG_X30)
return false;
*enc_out = 0;
return true;
}

/* index0: index of B subreg in Q register: 0-15 */

static inline bool
Expand Down Expand Up @@ -2332,7 +2350,11 @@ static inline bool
decode_opnds_b(uint enc, dcontext_t *dcontext, byte *pc, instr_t *instr, int opcode)
{
instr_set_opcode(instr, opcode);
instr_set_num_opnds(dcontext, instr, 0, 1);
if (opcode == OP_bl) {
instr_set_num_opnds(dcontext, instr, 1, 1);
instr_set_dst(instr, 0, opnd_create_reg(DR_REG_X30));
} else
instr_set_num_opnds(dcontext, instr, 0, 1);
instr_set_src(instr, 0, opnd_create_pc(pc + extract_int(enc, 0, 26) * 4));
return true;
}
Expand All @@ -2341,7 +2363,9 @@ static inline uint
encode_opnds_b(byte *pc, instr_t *instr, uint enc)
{
uint off;
if (instr_num_dsts(instr) == 0 && instr_num_srcs(instr) == 1 &&
if (((instr_get_opcode(instr) == OP_bl && instr_num_dsts(instr) == 1) ||
instr_num_dsts(instr) == 0) &&
instr_num_srcs(instr) == 1 &&
encode_pc_off(&off, 26, pc, instr, instr_get_src(instr, 0)))
return (enc | off);
return ENCFAIL;
Expand Down
3 changes: 2 additions & 1 deletion core/arch/aarch64/codec.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
# In register operands (e.g. w10) the number refers to the position of the lowest bit.
# In memory operands (e.g. mem7) the number refers to the number of offset bits.

-------------------------------- impx30 # Implicit X30 operand
-------------------------------- lsl # LSL for ADD/MOV (immediate)
----------------------------xxxx nzcv # flag bit specifier for CCMN, CCMP
---------------------------xxxxx b0 # B register
Expand Down Expand Up @@ -257,7 +258,7 @@ x0110111xxxxxxxxxxxxxxxxxxxxxxxx tbnz tbz
## Unconditional branch (register)

1101011000011111000000xxxxx00000 br : x5
1101011000111111000000xxxxx00000 blr : x5
1101011000111111000000xxxxx00000 blr impx30: x5
1101011001011111000000xxxxx00000 ret : x5

# Loads and Stores
Expand Down
16 changes: 15 additions & 1 deletion core/arch/aarch64/decode_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -4448,6 +4448,20 @@ decode_opndsgen_d61f0000(uint enc, dcontext_t *dcontext, byte *pc, instr_t *inst
return true;
}

static bool
decode_opndsgen_d63f0000(uint enc, dcontext_t *dcontext, byte *pc, instr_t *instr, int opcode)
{
opnd_t dst0, src0;
if (!decode_opnd_impx30(enc & 0xfffffc1f, opcode, pc, &dst0) ||
!decode_opnd_x5(enc & 0xffffffff, opcode, pc, &src0))
return false;
instr_set_opcode(instr, opcode);
instr_set_num_opnds(dcontext, instr, 1, 1);
instr_set_dst(instr, 0, dst0);
instr_set_src(instr, 0, src0);
return true;
}

static bool
decode_opndsgen_d8000000(uint enc, dcontext_t *dcontext, byte *pc, instr_t *instr, int opcode)
{
Expand Down Expand Up @@ -5294,7 +5308,7 @@ decoder(uint enc, dcontext_t *dc, byte *pc, instr_t *instr)
return decode_opndsgen_5c000000(enc, dc, pc, instr, OP_ldr);
} else {
if ((enc & 0xfffffc1f) == 0xd63f0000)
return decode_opndsgen_d61f0000(enc, dc, pc, instr, OP_blr);
return decode_opndsgen_d63f0000(enc, dc, pc, instr, OP_blr);
if ((enc & 0xffe0001f) == 0xd4200000)
return decode_opndsgen_d4000001(enc, dc, pc, instr, OP_brk);
}
Expand Down
20 changes: 19 additions & 1 deletion core/arch/aarch64/encode_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -5985,6 +5985,24 @@ encode_opndsgen_d61f0000(byte *pc, instr_t *instr, uint enc)
return ENCFAIL;
}

static uint
encode_opndsgen_d63f0000(byte *pc, instr_t *instr, uint enc)
{
int opcode = instr->opcode;
uint dst0, src0;
if (instr_num_dsts(instr) == 1 && instr_num_srcs(instr) == 1 &&
encode_opnd_impx30(enc & 0xfffffc1f, opcode, pc, instr_get_dst(instr, 0), &dst0) &&
encode_opnd_x5(enc & 0xffffffff, opcode, pc, instr_get_src(instr, 0), &src0)) {
ASSERT((dst0 & 0xffffffff) == 0);
ASSERT((src0 & 0xfffffc1f) == 0);
enc |= dst0 | src0;
if (dst0 == (enc & 0x00000000) &&
src0 == (enc & 0x000003e0))
return enc;
}
return ENCFAIL;
}

static uint
encode_opndsgen_d8000000(byte *pc, instr_t *instr, uint enc)
{
Expand Down Expand Up @@ -6526,7 +6544,7 @@ encoder(byte *pc, instr_t *instr)
case OP_bl:
return encode_opnds_b(pc, instr, 0x94000000);
case OP_blr:
return encode_opndsgen_d61f0000(pc, instr, 0xd63f0000);
return encode_opndsgen_d63f0000(pc, instr, 0xd63f0000);
case OP_br:
return encode_opndsgen_d61f0000(pc, instr, 0xd61f0000);
case OP_brk:
Expand Down
2 changes: 1 addition & 1 deletion core/arch/aarch64/instr_create.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@
#define INSTR_CREATE_br(dc, xn) \
instr_create_0dst_1src((dc), OP_br, (xn))
#define INSTR_CREATE_blr(dc, xn) \
instr_create_0dst_1src((dc), OP_blr, (xn))
instr_create_1dst_1src((dc), OP_blr, opnd_create_reg(DR_REG_X30), (xn))
#define INSTR_CREATE_brk(dc, imm) \
instr_create_0dst_1src((dc), OP_brk, (imm))
#define INSTR_CREATE_cbnz(dc, pc, reg) \
Expand Down
12 changes: 6 additions & 6 deletions suite/tests/api/dis-a64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -948,9 +948,9 @@
937fffff : asr xzr, xzr, #63 : sbfm %xzr $0x3f $0x3f -> %xzr
93c31041 : extr x1, x2, x3, #4 : extr %x2 %x3 $0x04 -> %x1
93dfffff : ror xzr, xzr, #63 : extr %xzr %xzr $0x3f -> %xzr
94081041 : bl 10204104 : bl $0x0000000010204104
96000000 : bl 8000000 : bl $0x0000000008000000
97ffffff : bl ffffffc : bl $0x000000000ffffffc
94081041 : bl 10204104 : bl $0x0000000010204104 -> %x30
96000000 : bl 8000000 : bl $0x0000000008000000 -> %x30
97ffffff : bl ffffffc : bl $0x000000000ffffffc -> %x30
98081041 : ldrsw x1, 10010208 : ldrsw <rel> 0x0000000010010208[4byte] -> %x1
987fffff : ldrsw xzr, 100ffffc : ldrsw <rel> 0x00000000100ffffc[4byte] -> %xzr
98800000 : ldrsw x0, ff00000 : ldrsw <rel> 0x000000000ff00000[4byte] -> %x0
Expand Down Expand Up @@ -1322,9 +1322,9 @@ d53fffff : mrs xzr, s3_7_c15_c15_7 : mrs $0x7fff -> %xzr
d61f0000 : br x0 : br %x0
d61f0040 : br x2 : br %x2
d61f03e0 : br xzr : br %xzr
d63f0000 : blr x0 : blr %x0
d63f0040 : blr x2 : blr %x2
d63f03e0 : blr xzr : blr %xzr
d63f0000 : blr x0 : blr %x0 -> %x30
d63f0040 : blr x2 : blr %x2 -> %x30
d63f03e0 : blr xzr : blr %xzr -> %x30
d65f0000 : ret x0 : ret %x0
d65f0040 : ret x2 : ret %x2
d65f03e0 : ret xzr : ret %xzr
Expand Down

0 comments on commit 3275b81

Please sign in to comment.