Skip to content

Commit

Permalink
i#1569 AArch64: Make dst reg also a src reg for BFM. (#2309)
Browse files Browse the repository at this point in the history
The BFM instruction (bitfield move) copies a number of bits from the
source to the destination register, leaving other bits unchanged.
This means the destination register must also be a source register,
otherwise DynamoRIO may not restore the original value of the
destination before a BFM instruction.
  • Loading branch information
fhahn committed Mar 28, 2017
1 parent 93fd96a commit 2c4c19c
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 12 deletions.
4 changes: 2 additions & 2 deletions core/arch/aarch64/codec.txt
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,10 @@ x11100100xxxxxxxxxxxxxxxxxxxxxxx ands logic_imm
## Bitfield

0001001100xxxxxxxxxxxxxxxxxxxxxx sbfm w0 : w5 immr imms
0011001100xxxxxxxxxxxxxxxxxxxxxx bfm w0 : w5 immr imms
0011001100xxxxxxxxxxxxxxxxxxxxxx bfm w0 : w0 w5 immr imms
0101001100xxxxxxxxxxxxxxxxxxxxxx ubfm w0 : w5 immr imms
1001001101xxxxxxxxxxxxxxxxxxxxxx sbfm x0 : x5 immr imms
1011001101xxxxxxxxxxxxxxxxxxxxxx bfm x0 : x5 immr imms
1011001101xxxxxxxxxxxxxxxxxxxxxx bfm x0 : x0 x5 immr imms
1101001101xxxxxxxxxxxxxxxxxxxxxx ubfm x0 : x5 immr imms

## Extract
Expand Down
48 changes: 44 additions & 4 deletions core/arch/aarch64/decode_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -2624,6 +2624,26 @@ decode_opndsgen_31000000(uint enc, dcontext_t *dcontext, byte *pc, instr_t *inst
return true;
}

static bool
decode_opndsgen_33000000(uint enc, dcontext_t *dcontext, byte *pc, instr_t *instr, int opcode)
{
opnd_t dst0, src0, src1, src2, src3;
if (!decode_opnd_w0(enc & 0xffc0001f, opcode, pc, &dst0) ||
!decode_opnd_w0(enc & 0xffc0001f, opcode, pc, &src0) ||
!decode_opnd_w5(enc & 0xffc003e0, opcode, pc, &src1) ||
!decode_opnd_immr(enc & 0xffff0000, opcode, pc, &src2) ||
!decode_opnd_imms(enc & 0xffc0fc00, opcode, pc, &src3))
return false;
instr_set_opcode(instr, opcode);
instr_set_num_opnds(dcontext, instr, 1, 4);
instr_set_dst(instr, 0, dst0);
instr_set_src(instr, 0, src0);
instr_set_src(instr, 1, src1);
instr_set_src(instr, 2, src2);
instr_set_src(instr, 3, src3);
return true;
}

static bool
decode_opndsgen_38000000(uint enc, dcontext_t *dcontext, byte *pc, instr_t *instr, int opcode)
{
Expand Down Expand Up @@ -4048,6 +4068,26 @@ decode_opndsgen_adc00000(uint enc, dcontext_t *dcontext, byte *pc, instr_t *inst
return true;
}

static bool
decode_opndsgen_b3400000(uint enc, dcontext_t *dcontext, byte *pc, instr_t *instr, int opcode)
{
opnd_t dst0, src0, src1, src2, src3;
if (!decode_opnd_x0(enc & 0xffc0001f, opcode, pc, &dst0) ||
!decode_opnd_x0(enc & 0xffc0001f, opcode, pc, &src0) ||
!decode_opnd_x5(enc & 0xffc003e0, opcode, pc, &src1) ||
!decode_opnd_immr(enc & 0xffff0000, opcode, pc, &src2) ||
!decode_opnd_imms(enc & 0xffc0fc00, opcode, pc, &src3))
return false;
instr_set_opcode(instr, opcode);
instr_set_num_opnds(dcontext, instr, 1, 4);
instr_set_dst(instr, 0, dst0);
instr_set_src(instr, 0, src0);
instr_set_src(instr, 1, src1);
instr_set_src(instr, 2, src2);
instr_set_src(instr, 3, src3);
return true;
}

static bool
decode_opndsgen_bc000000(uint enc, dcontext_t *dcontext, byte *pc, instr_t *instr, int opcode)
{
Expand Down Expand Up @@ -5563,7 +5603,7 @@ decoder(uint enc, dcontext_t *dc, byte *pc, instr_t *instr)
if ((enc & 0xff208000) == 0x2b000000)
return decode_opndsgen_0b000000(enc, dc, pc, instr, OP_adds);
if ((enc & 0xffc00000) == 0x33000000)
return decode_opndsgen_13000000(enc, dc, pc, instr, OP_bfm);
return decode_opndsgen_33000000(enc, dc, pc, instr, OP_bfm);
}
}
} else {
Expand Down Expand Up @@ -5722,7 +5762,7 @@ decoder(uint enc, dcontext_t *dc, byte *pc, instr_t *instr)
if ((enc & 0x7fe00000) == 0x2b200000)
return decode_opndsgen_2b200000(enc, dc, pc, instr, OP_adds);
if ((enc & 0xffc00000) == 0x33000000)
return decode_opndsgen_13000000(enc, dc, pc, instr, OP_bfm);
return decode_opndsgen_33000000(enc, dc, pc, instr, OP_bfm);
}
}
}
Expand Down Expand Up @@ -8676,7 +8716,7 @@ decoder(uint enc, dcontext_t *dc, byte *pc, instr_t *instr)
if ((enc & 0xff200000) == 0xab000000)
return decode_opndsgen_0b000000(enc, dc, pc, instr, OP_adds);
if ((enc & 0xffc00000) == 0xb3400000)
return decode_opndsgen_93400000(enc, dc, pc, instr, OP_bfm);
return decode_opndsgen_b3400000(enc, dc, pc, instr, OP_bfm);
}
}
} else {
Expand Down Expand Up @@ -8893,7 +8933,7 @@ decoder(uint enc, dcontext_t *dc, byte *pc, instr_t *instr)
if ((enc & 0x7f800000) == 0x31000000)
return decode_opndsgen_31000000(enc, dc, pc, instr, OP_adds);
if ((enc & 0xffc00000) == 0xb3400000)
return decode_opndsgen_93400000(enc, dc, pc, instr, OP_bfm);
return decode_opndsgen_b3400000(enc, dc, pc, instr, OP_bfm);
} else {
if ((enc & 0xffc00000) == 0xa9400000)
return decode_opndsgen_69400000(enc, dc, pc, instr, OP_ldp);
Expand Down
58 changes: 56 additions & 2 deletions core/arch/aarch64/encode_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -3573,6 +3573,33 @@ encode_opndsgen_31000000(byte *pc, instr_t *instr, uint enc)
return ENCFAIL;
}

static uint
encode_opndsgen_33000000(byte *pc, instr_t *instr, uint enc)
{
int opcode = instr->opcode;
uint dst0, src0, src1, src2, src3;
if (instr_num_dsts(instr) == 1 && instr_num_srcs(instr) == 4 &&
encode_opnd_w0(enc & 0xffc0001f, opcode, pc, instr_get_dst(instr, 0), &dst0) &&
encode_opnd_w0(enc & 0xffc0001f, opcode, pc, instr_get_src(instr, 0), &src0) &&
encode_opnd_w5(enc & 0xffc003e0, opcode, pc, instr_get_src(instr, 1), &src1) &&
encode_opnd_immr(enc & 0xffff0000, opcode, pc, instr_get_src(instr, 2), &src2) &&
encode_opnd_imms(enc & 0xffc0fc00, opcode, pc, instr_get_src(instr, 3), &src3)) {
ASSERT((dst0 & 0xffffffe0) == 0);
ASSERT((src0 & 0xffffffe0) == 0);
ASSERT((src1 & 0xfffffc1f) == 0);
ASSERT((src2 & 0xffc0ffff) == 0);
ASSERT((src3 & 0xffff03ff) == 0);
enc |= dst0 | src0 | src1 | src2 | src3;
if (dst0 == (enc & 0x0000001f) &&
src0 == (enc & 0x0000001f) &&
src1 == (enc & 0x000003e0) &&
src2 == (enc & 0x003f0000) &&
src3 == (enc & 0x0000fc00))
return enc;
}
return ENCFAIL;
}

static uint
encode_opndsgen_38000000(byte *pc, instr_t *instr, uint enc)
{
Expand Down Expand Up @@ -5463,6 +5490,33 @@ encode_opndsgen_adc00000(byte *pc, instr_t *instr, uint enc)
return ENCFAIL;
}

static uint
encode_opndsgen_b3400000(byte *pc, instr_t *instr, uint enc)
{
int opcode = instr->opcode;
uint dst0, src0, src1, src2, src3;
if (instr_num_dsts(instr) == 1 && instr_num_srcs(instr) == 4 &&
encode_opnd_x0(enc & 0xffc0001f, opcode, pc, instr_get_dst(instr, 0), &dst0) &&
encode_opnd_x0(enc & 0xffc0001f, opcode, pc, instr_get_src(instr, 0), &src0) &&
encode_opnd_x5(enc & 0xffc003e0, opcode, pc, instr_get_src(instr, 1), &src1) &&
encode_opnd_immr(enc & 0xffff0000, opcode, pc, instr_get_src(instr, 2), &src2) &&
encode_opnd_imms(enc & 0xffc0fc00, opcode, pc, instr_get_src(instr, 3), &src3)) {
ASSERT((dst0 & 0xffffffe0) == 0);
ASSERT((src0 & 0xffffffe0) == 0);
ASSERT((src1 & 0xfffffc1f) == 0);
ASSERT((src2 & 0xffc0ffff) == 0);
ASSERT((src3 & 0xffff03ff) == 0);
enc |= dst0 | src0 | src1 | src2 | src3;
if (dst0 == (enc & 0x0000001f) &&
src0 == (enc & 0x0000001f) &&
src1 == (enc & 0x000003e0) &&
src2 == (enc & 0x003f0000) &&
src3 == (enc & 0x0000fc00))
return enc;
}
return ENCFAIL;
}

static uint
encode_opndsgen_bc000000(byte *pc, instr_t *instr, uint enc)
{
Expand Down Expand Up @@ -6445,9 +6499,9 @@ encoder(byte *pc, instr_t *instr)
case OP_bcond:
return encode_opnds_bcond(pc, instr, 0x54000000);
case OP_bfm:
if ((enc = encode_opndsgen_13000000(pc, instr, 0x33000000)) != ENCFAIL)
if ((enc = encode_opndsgen_33000000(pc, instr, 0x33000000)) != ENCFAIL)
return enc;
return encode_opndsgen_93400000(pc, instr, 0xb3400000);
return encode_opndsgen_b3400000(pc, instr, 0xb3400000);
case OP_bic:
if ((enc = encode_opndsgen_0a000000(pc, instr, 0x0a200000)) != ENCFAIL)
return enc;
Expand Down
8 changes: 4 additions & 4 deletions suite/tests/api/dis-a64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@
31000c41 : adds w1, w2, #0x3 : adds %w2 $0x0003 lsl $0x00 -> %w1
31000fff : cmn wsp, #0x3 : adds %wsp $0x0003 lsl $0x00 -> %wzr
32000441 : orr w1, w2, #0x3 : orr %w2 $0x00000003 -> %w1
33031041 : bfxil w1, w2, #3, #2 : bfm %w2 $0x03 $0x04 -> %w1
331f7fff : bfxil wzr, wzr, #31, #1 : bfm %wzr $0x1f $0x1f -> %wzr
33031041 : bfxil w1, w2, #3, #2 : bfm %w1 %w2 $0x03 $0x04 -> %w1
331f7fff : bfxil wzr, wzr, #31, #1 : bfm %wzr %wzr $0x1f $0x1f -> %wzr
34081041 : cbz w1, 10010208 : cbz $0x0000000010010208 %w1
347fffff : cbz wzr, 100ffffc : cbz $0x00000000100ffffc %wzr
35081041 : cbnz w1, 10010208 : cbnz $0x0000000010010208 %w1
Expand Down Expand Up @@ -1015,8 +1015,8 @@ adffffff : ldp q31, q31, [sp,#-16]! : ldp -0x10(%sp)[32byte] %sp $0xfff
b1000c41 : adds x1, x2, #0x3 : adds %x2 $0x0003 lsl $0x00 -> %x1
b1000fff : cmn sp, #0x3 : adds %sp $0x0003 lsl $0x00 -> %xzr
b2400441 : orr x1, x2, #0x3 : orr %x2 $0x0000000000000003 -> %x1
b3431041 : bfxil x1, x2, #3, #2 : bfm %x2 $0x03 $0x04 -> %x1
b37fffff : bfxil xzr, xzr, #63, #1 : bfm %xzr $0x3f $0x3f -> %xzr
b3431041 : bfxil x1, x2, #3, #2 : bfm %x1 %x2 $0x03 $0x04 -> %x1
b37fffff : bfxil xzr, xzr, #63, #1 : bfm %xzr %xzr $0x3f $0x3f -> %xzr
b4ffffff : cbz xzr, ffffffc : cbz $0x000000000ffffffc %xzr
b5800000 : cbnz x0, ff00000 : cbnz $0x000000000ff00000 %x0
b5ffffff : cbnz xzr, ffffffc : cbnz $0x000000000ffffffc %xzr
Expand Down

0 comments on commit 2c4c19c

Please sign in to comment.