diff --git a/api/docs/release.dox b/api/docs/release.dox index e26e98925c9..6d6f97c48bd 100644 --- a/api/docs/release.dox +++ b/api/docs/release.dox @@ -126,7 +126,7 @@ clients. The changes between version \DR_VERSION and 10.0.0 include the following compatibility changes: - - Nothing yet. + - Marked x86 rep instructions as predicated. Further non-compatibility-affecting changes include: - Nothing yet. diff --git a/core/ir/x86/decode_table.c b/core/ir/x86/decode_table.c index d659e211270..8971f67fe9a 100644 --- a/core/ir/x86/decode_table.c +++ b/core/ir/x86/decode_table.c @@ -9534,61 +9534,61 @@ const instr_info_t rep_extensions[][4] = { {OP_ins, 0x6c0000, "ins", Yb, axDI, dx, axDI, xx, no, fRD, END_LIST}, {INVALID, 0x00000000, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, {OP_rep_ins, 0xf36c0000, "rep ins", Yb, axDI, dx, axDI, axCX, xop_next, fRD, END_LIST}, - {OP_CONTD, 0xf36c0000, "rep ins", axCX, xx, xx, xx, xx, no, fRD, END_LIST}, + {OP_CONTD, 0xf36c0000, "rep ins", axCX, xx, xx, xx, xx, predcx, fRD, END_LIST}, }, { /* rep extension 1 */ {OP_ins, 0x6d0000, "ins", Yz, axDI, dx, axDI, xx, no, fRD, tre[0][0]}, {INVALID, 0x00000000, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, - {OP_rep_ins, 0xf36d0000, "rep ins", Yz, axDI, dx, axDI, axCX, xop_next, fRD, tre[0][2]}, - {OP_CONTD, 0xf36d0000, "rep ins", axCX, xx, xx, xx, xx, no, fRD, END_LIST}, + {OP_rep_ins, 0xf36d0000, "rep ins", Yz, axDI, dx, axDI, axCX, xop_next|predcx, fRD, tre[0][2]}, + {OP_CONTD, 0xf36d0000, "rep ins", axCX, xx, xx, xx, xx, predcx, fRD, END_LIST}, }, { /* rep extension 2 */ {OP_outs, 0x6e0000, "outs", axSI, xx, Xb, dx, axSI, no, fRD, END_LIST}, {INVALID, 0x00000000, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, {OP_rep_outs, 0xf36e0000, "rep outs", axSI, axCX, Xb, dx, axSI, xop_next, fRD, END_LIST}, - {OP_CONTD, 0xf36e0000, "rep outs", xx, xx, axCX, xx, xx, no, fRD, END_LIST}, + {OP_CONTD, 0xf36e0000, "rep outs", xx, xx, axCX, xx, xx, predcx, fRD, END_LIST}, }, { /* rep extension 3 */ {OP_outs, 0x6f0000, "outs", axSI, xx, Xz, dx, axSI, no, fRD, tre[2][0]}, {INVALID, 0x00000000, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, - {OP_rep_outs, 0xf36f0000, "rep outs", axSI, axCX, Xz, dx, axSI, xop_next, fRD, tre[2][2]}, - {OP_CONTD, 0xf36f0000, "rep outs", xx, xx, axCX, xx, xx, no, fRD, END_LIST}, + {OP_rep_outs, 0xf36f0000, "rep outs", axSI, axCX, Xz, dx, axSI, xop_next|predcx, fRD, tre[2][2]}, + {OP_CONTD, 0xf36f0000, "rep outs", xx, xx, axCX, xx, xx, predcx, fRD, END_LIST}, }, { /* rep extension 4 */ {OP_movs, 0xa40000, "movs", Yb, axSI, Xb, axSI, axDI, xop_next, fRD, END_LIST}, {OP_CONTD, 0xa40000, "movs", axDI, xx, xx, xx, xx, no, fRD, END_LIST}, {OP_rep_movs, 0xf3a40000, "rep movs", Yb, axSI, Xb, axSI, axDI, xop_next, fRD, END_LIST}, - {OP_CONTD, 0xf3a40000, "rep movs", axDI, axCX, axCX, xx, xx, no, fRD, END_LIST}, + {OP_CONTD, 0xf3a40000, "rep movs", axDI, axCX, axCX, xx, xx, predcx, fRD, END_LIST}, }, { /* rep extension 5 */ {OP_movs, 0xa50000, "movs", Yv, axSI, Xv, axSI, axDI, xop_next, fRD, tre[4][0]}, {OP_CONTD, 0xa50000, "movs", axDI, xx, xx, xx, xx, no, fRD, END_LIST}, - {OP_rep_movs, 0xf3a50000, "rep movs", Yv, axSI, Xv, axSI, axDI, xop_next, fRD, tre[4][2]}, - {OP_CONTD, 0xf3a50000, "rep movs", axDI, axCX, axCX, xx, xx, no, fRD, END_LIST}, + {OP_rep_movs, 0xf3a50000, "rep movs", Yv, axSI, Xv, axSI, axDI, xop_next|predcx, fRD, tre[4][2]}, + {OP_CONTD, 0xf3a50000, "rep movs", axDI, axCX, axCX, xx, xx, predcx, fRD, END_LIST}, }, { /* rep extension 6 */ {OP_stos, 0xaa0000, "stos", Yb, axDI, al, axDI, xx, no, fRD, END_LIST}, {INVALID, 0x00000000, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, {OP_rep_stos, 0xf3aa0000, "rep stos", Yb, axDI, al, axDI, axCX, xop_next, fRD, END_LIST}, - {OP_CONTD, 0xf3aa0000, "rep stos", axCX, xx, xx, xx, xx, no, fRD, END_LIST}, + {OP_CONTD, 0xf3aa0000, "rep stos", axCX, xx, xx, xx, xx, predcx, fRD, END_LIST}, }, { /* rep extension 7 */ {OP_stos, 0xab0000, "stos", Yv, axDI, eAX, axDI, xx, no, fRD, tre[6][0]}, {INVALID, 0x00000000, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, - {OP_rep_stos, 0xf3ab0000, "rep stos", Yv, axDI, eAX, axDI, axCX, xop_next, fRD, tre[6][2]}, - {OP_CONTD, 0xf3ab0000, "rep stos", axCX, xx, xx, xx, xx, no, fRD, END_LIST}, + {OP_rep_stos, 0xf3ab0000, "rep stos", Yv, axDI, eAX, axDI, axCX, xop_next|predcx, fRD, tre[6][2]}, + {OP_CONTD, 0xf3ab0000, "rep stos", axCX, xx, xx, xx, xx, predcx, fRD, END_LIST}, }, { /* rep extension 8 */ {OP_lods, 0xac0000, "lods", al, axSI, Xb, axSI, xx, no, fRD, END_LIST}, {INVALID, 0x00000000, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, {OP_rep_lods, 0xf3ac0000, "rep lods", al, axSI, Xb, axSI, axCX, xop_next, fRD, END_LIST}, - {OP_CONTD, 0xf3ac0000, "rep lods", axCX, xx, xx, xx, xx, no, fRD, END_LIST}, + {OP_CONTD, 0xf3ac0000, "rep lods", axCX, xx, xx, xx, xx, predcx, fRD, END_LIST}, }, { /* rep extension 9 */ {OP_lods, 0xad0000, "lods", eAX, axSI, Xv, axSI, xx, no, fRD, tre[8][0]}, {INVALID, 0x00000000, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, - {OP_rep_lods, 0xf3ad0000, "rep lods", eAX, axSI, Xv, axSI, axCX, xop_next, fRD, tre[8][2]}, - {OP_CONTD, 0xf3ad0000, "rep lods", axCX, xx, xx, xx, xx, no, fRD, END_LIST}, + {OP_rep_lods, 0xf3ad0000, "rep lods", eAX, axSI, Xv, axSI, axCX, xop_next|predcx, fRD, tre[8][2]}, + {OP_CONTD, 0xf3ad0000, "rep lods", axCX, xx, xx, xx, xx, predcx, fRD, END_LIST}, }, }; @@ -9597,33 +9597,33 @@ const instr_info_t repne_extensions[][6] = { {OP_cmps, 0xa60000, "cmps", axSI, axDI, Xb, Yb, axSI, xop_next, (fW6|fRD), END_LIST}, {OP_CONTD, 0xa60000, "cmps", xx, xx, axDI, xx, xx, no, (fW6|fRD), END_LIST}, {OP_rep_cmps, 0xf3a60000, "rep cmps", axSI, axDI, Xb, Yb, axSI, xop_next, (fW6|fRD|fRZ), END_LIST}, - {OP_CONTD, 0xf3a60000, "rep cmps", axCX, xx, axDI, axCX, xx, no, (fW6|fRD), END_LIST}, + {OP_CONTD, 0xf3a60000, "rep cmps", axCX, xx, axDI, axCX, xx, predcx, (fW6|fRD|fRZ), END_LIST}, {OP_repne_cmps, 0xf2a60000, "repne cmps", axSI, axDI, Xb, Yb, axSI, xop_next, (fW6|fRD|fRZ), END_LIST}, - {OP_CONTD, 0xf2a60000, "repne cmps", axCX, xx, axDI, axCX, xx, no, (fW6|fRD), END_LIST}, + {OP_CONTD, 0xf2a60000, "repne cmps", axCX, xx, axDI, axCX, xx, predcx, (fW6|fRD|fRZ), END_LIST}, }, { /* repne extension 1 */ {OP_cmps, 0xa70000, "cmps", axSI, axDI, Xv, Yv, axSI, xop_next, (fW6|fRD), tne[0][0]}, {OP_CONTD, 0xa70000, "cmps", xx, xx, axDI, xx, xx, no, (fW6|fRD), END_LIST}, - {OP_rep_cmps, 0xf3a70000, "rep cmps", axSI, axDI, Xv, Yv, axSI, xop_next, (fW6|fRD|fRZ), tne[0][2]}, - {OP_CONTD, 0xf3a70000, "rep cmps", axCX, xx, axDI, axCX, xx, no, (fW6|fRD), END_LIST}, - {OP_repne_cmps, 0xf2a70000, "repne cmps", axSI, axDI, Xv, Yv, axSI, xop_next, (fW6|fRD|fRZ), tne[0][4]}, - {OP_CONTD, 0xf2a70000, "repne cmps", axCX, xx, axDI, axCX, xx, no, (fW6|fRD), END_LIST}, + {OP_rep_cmps, 0xf3a70000, "rep cmps", axSI, axDI, Xv, Yv, axSI, xop_next|predcx, (fW6|fRD|fRZ), tne[0][2]}, + {OP_CONTD, 0xf3a70000, "rep cmps", axCX, xx, axDI, axCX, xx, predcx, (fW6|fRD|fRZ), END_LIST}, + {OP_repne_cmps, 0xf2a70000, "repne cmps", axSI, axDI, Xv, Yv, axSI, xop_next|predcx, (fW6|fRD|fRZ), tne[0][4]}, + {OP_CONTD, 0xf2a70000, "repne cmps", axCX, xx, axDI, axCX, xx, predcx, (fW6|fRD|fRZ), END_LIST}, }, { /* repne extension 2 */ {OP_scas, 0xae0000, "scas", axDI, xx, Yb, al, axDI, no, (fW6|fRD), END_LIST}, {INVALID, 0x00000000, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, {OP_rep_scas, 0xf3ae0000, "rep scas", axDI, axCX, Yb, al, axDI, xop_next, (fW6|fRD|fRZ), END_LIST}, - {OP_CONTD, 0xf3ae0000, "rep scas", xx, xx, axCX, xx, xx, no, (fW6|fRD), END_LIST}, + {OP_CONTD, 0xf3ae0000, "rep scas", xx, xx, axCX, xx, xx, predcx, (fW6|fRD|fRZ), END_LIST}, {OP_repne_scas, 0xf2ae0000, "repne scas", axDI, axCX, Yb, al, axDI, xop_next, (fW6|fRD|fRZ), END_LIST}, - {OP_CONTD, 0xf2ae0000, "repne scas", xx, xx, axCX, xx, xx, no, (fW6|fRD), END_LIST}, + {OP_CONTD, 0xf2ae0000, "repne scas", xx, xx, axCX, xx, xx, predcx, (fW6|fRD|fRZ), END_LIST}, }, { /* repne extension 3 */ {OP_scas, 0xaf0000, "scas", axDI, xx, Yv, eAX, axDI, no, (fW6|fRD), tne[2][0]}, {INVALID, 0x00000000, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, - {OP_rep_scas, 0xf3af0000, "rep scas", axDI, axCX, Yv, eAX, axDI, xop_next, (fW6|fRD|fRZ), tne[2][2]}, - {OP_CONTD, 0xf3af0000, "rep scas", xx, xx, axCX, xx, xx, no, (fW6|fRD), END_LIST}, - {OP_repne_scas, 0xf2af0000, "repne scas", axDI, axCX, Yv, eAX, axDI, xop_next, (fW6|fRD|fRZ), tne[2][4]}, - {OP_CONTD, 0xf2af0000, "repne scas", xx, xx, axCX, xx, xx, no, (fW6|fRD), END_LIST}, + {OP_rep_scas, 0xf3af0000, "rep scas", axDI, axCX, Yv, eAX, axDI, xop_next|predcx, (fW6|fRD|fRZ), tne[2][2]}, + {OP_CONTD, 0xf3af0000, "rep scas", xx, xx, axCX, xx, xx, predcx, (fW6|fRD|fRZ), END_LIST}, + {OP_repne_scas, 0xf2af0000, "repne scas", axDI, axCX, Yv, eAX, axDI, xop_next|predcx, (fW6|fRD|fRZ), tne[2][4]}, + {OP_CONTD, 0xf2af0000, "repne scas", xx, xx, axCX, xx, xx, predcx, (fW6|fRD|fRZ), END_LIST}, } }; diff --git a/core/ir/x86/instr_create_api.h b/core/ir/x86/instr_create_api.h index 5a9b6e87559..7afdbee971f 100644 --- a/core/ir/x86/instr_create_api.h +++ b/core/ir/x86/instr_create_api.h @@ -4765,65 +4765,81 @@ opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, \ 0, 0, OPSZ_4_rex8_short2), \ opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI)) -#define INSTR_CREATE_rep_ins_1(dc) \ - instr_create_3dst_3src( \ - (dc), OP_rep_ins, \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ - opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ - opnd_create_reg(DR_REG_DX), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_rep_ins_4(dc) \ - instr_create_3dst_3src((dc), OP_rep_ins, \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, \ - 0, 0, OPSZ_4_rex8_short2), \ - opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ - opnd_create_reg(DR_REG_DX), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_rep_stos_1(dc) \ - instr_create_3dst_3src( \ - (dc), OP_rep_stos, \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ - opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ - opnd_create_reg(DR_REG_AL), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_rep_stos_4(dc) \ - instr_create_3dst_3src((dc), OP_rep_stos, \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, \ - 0, 0, OPSZ_4_rex8_short2), \ - opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ - opnd_create_reg(DR_REG_EAX), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_rep_lods_1(dc) \ - instr_create_3dst_3src( \ - (dc), OP_rep_lods, opnd_create_reg(DR_REG_AL), opnd_create_reg(DR_REG_XSI), \ - opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, OPSZ_1), \ - opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_rep_lods_4(dc) \ - instr_create_3dst_3src((dc), OP_rep_lods, opnd_create_reg(DR_REG_EAX), \ - opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, \ - 0, 0, OPSZ_4_rex8_short2), \ - opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_rep_movs_1(dc) \ - instr_create_4dst_4src( \ - (dc), OP_rep_movs, \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ - opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, OPSZ_1), \ - opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_rep_movs_4(dc) \ - instr_create_4dst_4src((dc), OP_rep_movs, \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, \ - 0, 0, OPSZ_4_rex8_short2), \ - opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, \ - 0, 0, OPSZ_4_rex8_short2), \ - opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) +#define INSTR_CREATE_rep_ins_1(dc) \ + INSTR_PRED( \ + instr_create_3dst_3src( \ + (dc), OP_rep_ins, \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ + opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ + opnd_create_reg(DR_REG_DX), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_rep_ins_4(dc) \ + INSTR_PRED(instr_create_3dst_3src( \ + (dc), OP_rep_ins, \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, \ + OPSZ_4_rex8_short2), \ + opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ + opnd_create_reg(DR_REG_DX), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_rep_stos_1(dc) \ + INSTR_PRED( \ + instr_create_3dst_3src( \ + (dc), OP_rep_stos, \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ + opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ + opnd_create_reg(DR_REG_AL), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_rep_stos_4(dc) \ + INSTR_PRED(instr_create_3dst_3src( \ + (dc), OP_rep_stos, \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, \ + OPSZ_4_rex8_short2), \ + opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ + opnd_create_reg(DR_REG_EAX), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_rep_lods_1(dc) \ + INSTR_PRED( \ + instr_create_3dst_3src( \ + (dc), OP_rep_lods, opnd_create_reg(DR_REG_AL), opnd_create_reg(DR_REG_XSI), \ + opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, OPSZ_1), \ + opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_rep_lods_4(dc) \ + INSTR_PRED(instr_create_3dst_3src( \ + (dc), OP_rep_lods, opnd_create_reg(DR_REG_EAX), \ + opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, \ + OPSZ_4_rex8_short2), \ + opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_rep_movs_1(dc) \ + INSTR_PRED( \ + instr_create_4dst_4src( \ + (dc), OP_rep_movs, \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ + opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, OPSZ_1), \ + opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_rep_movs_4(dc) \ + INSTR_PRED(instr_create_4dst_4src( \ + (dc), OP_rep_movs, \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, \ + OPSZ_4_rex8_short2), \ + opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, \ + OPSZ_4_rex8_short2), \ + opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) #define INSTR_CREATE_outs_1(dc) \ instr_create_1dst_3src( \ (dc), OP_outs, opnd_create_reg(DR_REG_XSI), \ @@ -4858,79 +4874,100 @@ opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, \ 0, 0, OPSZ_4_rex8_short2), \ opnd_create_reg(DR_REG_EAX), opnd_create_reg(DR_REG_XDI)) -#define INSTR_CREATE_rep_outs_1(dc) \ - instr_create_2dst_4src( \ - (dc), OP_rep_outs, opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, OPSZ_1), \ - opnd_create_reg(DR_REG_DX), opnd_create_reg(DR_REG_XSI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_rep_outs_4(dc) \ - instr_create_2dst_4src((dc), OP_rep_outs, opnd_create_reg(DR_REG_XSI), \ - opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, \ - 0, 0, OPSZ_4_rex8_short2), \ - opnd_create_reg(DR_REG_DX), opnd_create_reg(DR_REG_XSI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_rep_cmps_1(dc) \ - instr_create_3dst_5src( \ - (dc), OP_rep_cmps, opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, OPSZ_1), \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ - opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_rep_cmps_4(dc) \ - instr_create_3dst_5src((dc), OP_rep_cmps, opnd_create_reg(DR_REG_XSI), \ - opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, \ - 0, 0, OPSZ_4_rex8_short2), \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, \ - 0, 0, OPSZ_4_rex8_short2), \ - opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_repne_cmps_1(dc) \ - instr_create_3dst_5src( \ - (dc), OP_repne_cmps, opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, OPSZ_1), \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ - opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_repne_cmps_4(dc) \ - instr_create_3dst_5src((dc), OP_repne_cmps, opnd_create_reg(DR_REG_XSI), \ - opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, \ - 0, 0, OPSZ_4_rex8_short2), \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, \ - 0, 0, OPSZ_4_rex8_short2), \ - opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_rep_scas_1(dc) \ - instr_create_2dst_4src( \ - (dc), OP_rep_scas, opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ - opnd_create_reg(DR_REG_AL), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_rep_scas_4(dc) \ - instr_create_2dst_4src((dc), OP_rep_scas, opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, \ - 0, 0, OPSZ_4_rex8_short2), \ - opnd_create_reg(DR_REG_EAX), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_repne_scas_1(dc) \ - instr_create_2dst_4src( \ - (dc), OP_repne_scas, opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ - opnd_create_reg(DR_REG_AL), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) -#define INSTR_CREATE_repne_scas_4(dc) \ - instr_create_2dst_4src((dc), OP_repne_scas, opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX), \ - opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, \ - 0, 0, OPSZ_4_rex8_short2), \ - opnd_create_reg(DR_REG_EAX), opnd_create_reg(DR_REG_XDI), \ - opnd_create_reg(DR_REG_XCX)) +#define INSTR_CREATE_rep_outs_1(dc) \ + INSTR_PRED( \ + instr_create_2dst_4src( \ + (dc), OP_rep_outs, opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, OPSZ_1), \ + opnd_create_reg(DR_REG_DX), opnd_create_reg(DR_REG_XSI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_rep_outs_4(dc) \ + INSTR_PRED(instr_create_2dst_4src( \ + (dc), OP_rep_outs, opnd_create_reg(DR_REG_XSI), \ + opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, \ + OPSZ_4_rex8_short2), \ + opnd_create_reg(DR_REG_DX), opnd_create_reg(DR_REG_XSI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_rep_cmps_1(dc) \ + INSTR_PRED( \ + instr_create_3dst_5src( \ + (dc), OP_rep_cmps, opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, OPSZ_1), \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ + opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_rep_cmps_4(dc) \ + INSTR_PRED(instr_create_3dst_5src( \ + (dc), OP_rep_cmps, opnd_create_reg(DR_REG_XSI), \ + opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, \ + OPSZ_4_rex8_short2), \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, \ + OPSZ_4_rex8_short2), \ + opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_repne_cmps_1(dc) \ + INSTR_PRED( \ + instr_create_3dst_5src( \ + (dc), OP_repne_cmps, opnd_create_reg(DR_REG_XSI), \ + opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, OPSZ_1), \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ + opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_repne_cmps_4(dc) \ + INSTR_PRED(instr_create_3dst_5src( \ + (dc), OP_repne_cmps, opnd_create_reg(DR_REG_XSI), \ + opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_DS, DR_REG_XSI, DR_REG_NULL, 0, 0, \ + OPSZ_4_rex8_short2), \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, \ + OPSZ_4_rex8_short2), \ + opnd_create_reg(DR_REG_XSI), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_rep_scas_1(dc) \ + INSTR_PRED( \ + instr_create_2dst_4src( \ + (dc), OP_rep_scas, opnd_create_reg(DR_REG_XDI), opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ + opnd_create_reg(DR_REG_AL), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_rep_scas_4(dc) \ + INSTR_PRED(instr_create_2dst_4src( \ + (dc), OP_rep_scas, opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, \ + OPSZ_4_rex8_short2), \ + opnd_create_reg(DR_REG_EAX), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_repne_scas_1(dc) \ + INSTR_PRED( \ + instr_create_2dst_4src( \ + (dc), OP_repne_scas, opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, OPSZ_1), \ + opnd_create_reg(DR_REG_AL), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) +#define INSTR_CREATE_repne_scas_4(dc) \ + INSTR_PRED(instr_create_2dst_4src( \ + (dc), OP_repne_scas, opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX), \ + opnd_create_far_base_disp(DR_SEG_ES, DR_REG_XDI, DR_REG_NULL, 0, 0, \ + OPSZ_4_rex8_short2), \ + opnd_create_reg(DR_REG_EAX), opnd_create_reg(DR_REG_XDI), \ + opnd_create_reg(DR_REG_XCX)), \ + DR_PRED_COMPLEX) /** @} */ /* end doxygen group */ /* floating point */ diff --git a/suite/tests/api/ir_x86.c b/suite/tests/api/ir_x86.c index ba40a3f9bd6..1e59b70e474 100644 --- a/suite/tests/api/ir_x86.c +++ b/suite/tests/api/ir_x86.c @@ -914,7 +914,8 @@ test_cti_prefixes(void *dc) } static void -test_cti_predicate(void *dc, byte *data, uint len, int opcode, dr_pred_type_t pred) +test_predicate(void *dc, byte *data, uint len, int opcode, dr_pred_type_t pred, + uint eflags) { instr_t *instr = instr_create(dc); byte *end = decode(dc, data, instr); @@ -922,6 +923,7 @@ test_cti_predicate(void *dc, byte *data, uint len, int opcode, dr_pred_type_t pr ASSERT(instr_get_opcode(instr) == opcode); ASSERT(instr_is_predicated(instr)); ASSERT(instr_get_predicate(instr) == pred); + ASSERT(instr_get_opcode_eflags(opcode) == eflags); instr_destroy(dc, instr); } @@ -936,9 +938,32 @@ test_cti_predicates(void *dc) // 0f 44 c2 cmovbe %edx,%eax { 0x0f, 0x46, 0xc2 }, }; - test_cti_predicate(dc, data[0], 2, OP_jle_short, DR_PRED_LE); - test_cti_predicate(dc, data[1], 6, OP_je, DR_PRED_EQ); - test_cti_predicate(dc, data[2], 3, OP_cmovbe, DR_PRED_BE); + test_predicate(dc, data[0], 2, OP_jle_short, DR_PRED_LE, + EFLAGS_READ_SF | EFLAGS_READ_OF | EFLAGS_READ_ZF); + test_predicate(dc, data[1], 6, OP_je, DR_PRED_EQ, EFLAGS_READ_ZF); + test_predicate(dc, data[2], 3, OP_cmovbe, DR_PRED_BE, + EFLAGS_READ_CF | EFLAGS_READ_ZF); +} + +static void +test_rep_predicates(void *dc) +{ + byte data[][16] = { + // f3 6c rep ins + { 0xf3, 0x6c }, + // f3 a4 rep movs + { 0xf3, 0xa4 }, + // f3 a6 rep cmps + { 0xf3, 0xa6 }, + // f2 af repne scas + { 0xf2, 0xaf }, + }; + test_predicate(dc, data[0], 2, OP_rep_ins, DR_PRED_COMPLEX, EFLAGS_READ_DF); + test_predicate(dc, data[1], 2, OP_rep_movs, DR_PRED_COMPLEX, EFLAGS_READ_DF); + test_predicate(dc, data[2], 2, OP_rep_cmps, DR_PRED_COMPLEX, + EFLAGS_WRITE_6 | EFLAGS_READ_DF | EFLAGS_READ_ZF); + test_predicate(dc, data[3], 2, OP_repne_scas, DR_PRED_COMPLEX, + EFLAGS_WRITE_6 | EFLAGS_READ_DF | EFLAGS_READ_ZF); } static void @@ -2870,6 +2895,8 @@ main(int argc, char *argv[]) test_cti_predicates(dcontext); + test_rep_predicates(dcontext); + #ifndef X64 test_modrm16(dcontext); #endif