Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i#2440: AArch64 v8.0 codec: add CCMP and CCMN INSTR_CREATE macros #5216

Merged
merged 5 commits into from
Nov 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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