Skip to content

Commit

Permalink
i#2440: AArch64 v8.0 codec: add CCMP and CCMN INSTR_CREATE macros (#5216
Browse files Browse the repository at this point in the history
)

This adds immediate and register variants of CCMP and CCMN to the
codec. The implementation also addresses the issues raised in
PR #4500.

Issues: #2440, #2443, #2626
  • Loading branch information
AssadHashmi authored Nov 23, 2021
1 parent 04d5d2d commit 75d7b48
Show file tree
Hide file tree
Showing 7 changed files with 875 additions and 13 deletions.
55 changes: 55 additions & 0 deletions core/ir/aarch64/codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -4356,6 +4356,61 @@ encode_opnds_bcond(byte *pc, instr_t *instr, uint enc, decode_info_t *di)
return ENCFAIL;
}

/* ccm: operands for conditional compare instructions */

static inline bool
decode_opnds_ccm(uint enc, dcontext_t *dcontext, byte *pc, instr_t *instr, int opcode)
{
instr_set_opcode(instr, opcode);
instr_set_num_opnds(dcontext, instr, 0, 3);

/* Rn */
opnd_t rn;
if (!decode_opnd_rn(false, 5, enc, &rn))
return false;
instr_set_src(instr, 0, rn);

opnd_t rm;
if (TEST(1U << 11, enc)) /* imm5 */
instr_set_src(instr, 1, opnd_create_immed_int(extract_uint(enc, 16, 5), OPSZ_5b));
else if (!decode_opnd_rn(false, 16, enc, &rm)) /* Rm */
return false;
else
instr_set_src(instr, 1, rm);

/* nzcv */
instr_set_src(instr, 2, opnd_create_immed_int(extract_uint(enc, 0, 4), OPSZ_4b));
/* cond */
instr_set_predicate(instr, DR_PRED_EQ + extract_uint(enc, 12, 4));

return true;
}

static inline uint
encode_opnds_ccm(byte *pc, instr_t *instr, uint enc, decode_info_t *di)
{
uint rn;
uint rm_imm5 = 0;
uint imm5_flag = 0;
if (instr_num_dsts(instr) == 0 && instr_num_srcs(instr) == 3 &&
encode_opnd_rn(false, 5, instr_get_src(instr, 0), &rn) && /* Rn */
opnd_is_immed_int(instr_get_src(instr, 2)) && /* nzcv */
(uint)(instr_get_predicate(instr) - DR_PRED_EQ) < 16) { /* cond */
uint nzcv = opnd_get_immed_int(instr_get_src(instr, 2));
uint cond = instr_get_predicate(instr) - DR_PRED_EQ;
if (opnd_is_immed_int(instr_get_src(instr, 1))) { /* imm5 */
rm_imm5 = opnd_get_immed_int(instr_get_src(instr, 1)) << 16;
imm5_flag = 1;
} else if (opnd_is_reg(instr_get_src(instr, 1))) { /* Rm */
encode_opnd_rn(false, 16, instr_get_src(instr, 1), &rm_imm5);
} else
return ENCFAIL;
return (enc | nzcv | rn | (imm5_flag << 11) | rm_imm5 | (cond << 12));
}

return ENCFAIL;
}

/* cbz: used for CBNZ and CBZ */

static inline bool
Expand Down
8 changes: 4 additions & 4 deletions core/ir/aarch64/codec.txt
Original file line number Diff line number Diff line change
Expand Up @@ -349,10 +349,10 @@ x1101010xx1xxxxxxxxxxxxxxxxxxxxx w 30 bics wx0 : wx5 wx16 s
01001000001xxxxx111111xxxxxxxxxx n 53 caspl x16p0 x16p1 mem0p : x16p0 x16p1 x0p0 x0p1 mem0p
x0110101xxxxxxxxxxxxxxxxxxxxxxxx n 54 cbnz cbz
x0110100xxxxxxxxxxxxxxxxxxxxxxxx n 55 cbz cbz
x0111010010xxxxxxxxx00xxxxx0xxxx rw 56 ccmn : wx5 wx16 nzcv cond
x0111010010xxxxxxxxx10xxxxx0xxxx rw 56 ccmn : wx5 imm5 nzcv cond
x1111010010xxxxxxxxx00xxxxx0xxxx rw 57 ccmp : wx5 wx16 nzcv cond
x1111010010xxxxxxxxx10xxxxx0xxxx rw 57 ccmp : wx5 imm5 nzcv cond
x0111010010xxxxxxxxx00xxxxx0xxxx w 56 ccmn ccm
x0111010010xxxxxxxxx10xxxxx0xxxx w 56 ccmn ccm
x1111010010xxxxxxxxx00xxxxx0xxxx w 57 ccmp ccm
x1111010010xxxxxxxxx10xxxxx0xxxx w 57 ccmp ccm
11010101000000110011xxxx01011111 n 58 clrex : imm4
x101101011000000000101xxxxxxxxxx n 59 cls wx0 : wx5
0x001110xx100000010010xxxxxxxxxx n 59 cls dq0 : dq5 bhs_sz
Expand Down
6 changes: 6 additions & 0 deletions core/ir/aarch64/disassemble.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ print_opcode_name(instr_t *instr, const char *name, char *buf, size_t bufsz,
if (instr_get_opcode(instr) == OP_bcond) {
print_to_buffer(buf, bufsz, sofar, "b.%s",
pred_names[instr_get_predicate(instr)]);
} else if (instr_get_opcode(instr) == OP_ccmp) {
print_to_buffer(buf, bufsz, sofar, "ccmp.%s",
pred_names[instr_get_predicate(instr)]);
} else if (instr_get_opcode(instr) == OP_ccmn) {
print_to_buffer(buf, bufsz, sofar, "ccmn.%s",
pred_names[instr_get_predicate(instr)]);
} else
print_to_buffer(buf, bufsz, sofar, "%s", name);
}
34 changes: 34 additions & 0 deletions core/ir/aarch64/instr_create_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,40 @@ enum {
#define INSTR_CREATE_bl(dc, pc) \
instr_create_1dst_1src((dc), OP_bl, opnd_create_reg(DR_REG_X30), (pc))

/**
* Creates a CCMP (Conditional Compare) instruction. Sets the NZCV flags to the
* result of a comparison of its two source values if the named input condition
* is true, or to an immediate value if the input condition is false.
* \param dc The void * dcontext used to allocate memory for the #instr_t.
* \param cond The comparison condition specified by #dr_pred_type_t, e.g. #DR_PRED_EQ.
* \param Rn The GPR source register.
* \param Op Either a 5-bit immediate (use #opnd_create_immed_uint() to create
the operand, e.g. opnd_create_immed_uint(val, #OPSZ_5b)) or a GPR source register.
* \param nzcv The 4 bit NZCV flags value used if the input condition is false.
* (use #opnd_create_immed_uint() to create the operand, e.g.
* opnd_create_immed_uint(val, #OPSZ_4b)).
*/
#define INSTR_CREATE_ccmp(dc, Rn, Op, nzcv, cond) \
(INSTR_PRED(instr_create_0dst_3src(dc, OP_ccmp, Rn, Op, nzcv), (cond)))

/**
* Creates a CCMN (Conditional Compare Negative) instruction. Sets the NZCV
* flags to the result of a comparison of its two source values if the named
* input condition is true, or to an immediate value if the input condition is
* false. The comparison is based on a negated second source value (Op) if an
* immediate, inverted if a register.
* \param dc The void * dcontext used to allocate memory for the #instr_t.
* \param cond The comparison condition specified by #dr_pred_type_t, e.g. #DR_PRED_EQ.
* \param Rn The GPR source register.
* \param Op Either a 5-bit immediate (use #opnd_create_immed_uint() to create the
* operand, e.g. opnd_create_immed_uint(val, #OPSZ_5b)) or a GPR source register.
* \param nzcv The 4 bit NZCV flags value used if the input condition is false.
* (use #opnd_create_immed_uint() to create the operand, e.g.
* opnd_create_immed_uint(val, #OPSZ_4b)).
*/
#define INSTR_CREATE_ccmn(dc, Rn, Op, nzcv, cond) \
(INSTR_PRED(instr_create_0dst_3src(dc, OP_ccmn, Rn, Op, nzcv), (cond)))

/** \cond disabled_until_i4106_is_fixed */
#define INSTR_CREATE_adc(dc, Rd, Rn, Rm) \
instr_create_1dst_2src((dc), OP_adc, (Rd), (Rn), (Rm))
Expand Down
Loading

0 comments on commit 75d7b48

Please sign in to comment.