From 1a66fecdbc0d0ca441b60213bcae767f18bbeb10 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Thu, 26 Jun 2014 12:09:15 +0800 Subject: [PATCH] x86: support avx_sae & avx_rm in cs_x86 struct. this also updates Python & Java bindings following the core's change --- arch/X86/X86ATTInstPrinter.c | 8 ++++---- arch/X86/X86Disassembler.c | 3 +++ arch/X86/X86GenAsmWriter.inc | 6 ++++-- arch/X86/X86GenAsmWriter1.inc | 4 +++- arch/X86/X86IntelInstPrinter.c | 8 ++++---- arch/X86/X86Mapping.c | 16 +++++++++++++++- arch/X86/X86Mapping.h | 6 +++++- bindings/java/TestX86.java | 6 ++++++ bindings/java/capstone/X86.java | 6 +++++- bindings/java/capstone/X86_const.java | 8 ++++++++ bindings/python/capstone/__init__.py | 3 ++- bindings/python/capstone/x86.py | 5 ++++- bindings/python/capstone/x86_const.py | 8 ++++++++ bindings/python/test_x86.py | 8 ++++++++ include/x86.h | 15 +++++++++++++++ tests/test_x86.c | 16 ++++++++++++++-- 16 files changed, 108 insertions(+), 18 deletions(-) diff --git a/arch/X86/X86ATTInstPrinter.c b/arch/X86/X86ATTInstPrinter.c index 13c3452c..e34c6cdc 100644 --- a/arch/X86/X86ATTInstPrinter.c +++ b/arch/X86/X86ATTInstPrinter.c @@ -213,10 +213,10 @@ static void printRoundingControl(MCInst *MI, unsigned Op, SStream *O) { int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x3; switch (Imm) { - case 0: SStream_concat0(O, "{rn-sae}"); break; - case 1: SStream_concat0(O, "{rd-sae}"); break; - case 2: SStream_concat0(O, "{ru-sae}"); break; - case 3: SStream_concat0(O, "{rz-sae}"); break; + case 0: SStream_concat0(O, "{rn-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RN); break; + case 1: SStream_concat0(O, "{rd-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RD); break; + case 2: SStream_concat0(O, "{ru-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RU); break; + case 3: SStream_concat0(O, "{rz-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RZ); break; default: break; // nev0er reach } } diff --git a/arch/X86/X86Disassembler.c b/arch/X86/X86Disassembler.c index 524e5fa4..ce647955 100644 --- a/arch/X86/X86Disassembler.c +++ b/arch/X86/X86Disassembler.c @@ -716,6 +716,9 @@ bool X86_getInstruction(csh ud, const uint8_t *code, size_t code_len, instr->flat_insn->detail->x86.op_count = 0; instr->flat_insn->detail->x86.sse_cc = X86_SSE_CC_INVALID; instr->flat_insn->detail->x86.avx_cc = X86_AVX_CC_INVALID; + instr->flat_insn->detail->x86.avx_sae = false; + instr->flat_insn->detail->x86.avx_rm = X86_AVX_RM_INVALID; + memset(instr->flat_insn->detail->x86.prefix, 0, sizeof(instr->flat_insn->detail->x86.prefix)); memset(instr->flat_insn->detail->x86.opcode, 0, sizeof(instr->flat_insn->detail->x86.opcode)); memset(instr->flat_insn->detail->x86.operands, 0, 4 * sizeof(instr->flat_insn->detail->x86.operands[0])); diff --git a/arch/X86/X86GenAsmWriter.inc b/arch/X86/X86GenAsmWriter.inc index 92c814c8..3b238844 100644 --- a/arch/X86/X86GenAsmWriter.inc +++ b/arch/X86/X86GenAsmWriter.inc @@ -13193,6 +13193,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) case 45: // VCMPPDZrrib SStream_concat0(O, "pd \t{sae}, "); + op_addAvxSae(MI); printOperand(MI, 2, O); SStream_concat0(O, ", "); printOperand(MI, 1, O); @@ -13207,6 +13208,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) case 47: // VCMPPSZrrib SStream_concat0(O, "ps \t{sae}, "); + op_addAvxSae(MI); printOperand(MI, 2, O); SStream_concat0(O, ", "); printOperand(MI, 1, O); @@ -13570,13 +13572,13 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) case 5: // VMOVDQU32rrkz, VMOVDQU64rrkz SStream_concat0(O, "} {z}"); - op_addZeroOpmask(MI); + op_addAvxZeroOpmask(MI); return; break; case 6: // VPBROADCASTDZkrm, VPBROADCASTDZkrr, VPBROADCASTDrZkrr, VPBROADCASTQZkr... SStream_concat0(O, "} {z}"); - op_addZeroOpmask(MI); + op_addAvxZeroOpmask(MI); return; break; case 7: diff --git a/arch/X86/X86GenAsmWriter1.inc b/arch/X86/X86GenAsmWriter1.inc index eccbfb92..6eab0e60 100644 --- a/arch/X86/X86GenAsmWriter1.inc +++ b/arch/X86/X86GenAsmWriter1.inc @@ -12823,6 +12823,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) case 5: // VCMPPDZrrib, VCMPPSZrrib, VRCP28PDZrb, VRCP28PSZrb, VRSQRT28PDZrb, VRS... SStream_concat0(O, ", {sae}"); + op_addAvxSae(MI); return; break; case 6: @@ -12838,7 +12839,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) case 8: // VMOVDQU32rrkz, VMOVDQU64rrkz, VPBROADCASTDZkrm, VPBROADCASTDZkrr, VPBR... SStream_concat0(O, "} {z}, "); - op_addZeroOpmask(MI); + op_addAvxZeroOpmask(MI); break; case 9: // VPCONFLICTDrmb @@ -13012,6 +13013,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) case 4: // VRCP28SDrrb, VRCP28SSrrb, VRSQRT28SDrrb, VRSQRT28SSrrb SStream_concat0(O, ", {sae}"); + op_addAvxSae(MI); return; break; } diff --git a/arch/X86/X86IntelInstPrinter.c b/arch/X86/X86IntelInstPrinter.c index 85adbe4e..6a0b7380 100644 --- a/arch/X86/X86IntelInstPrinter.c +++ b/arch/X86/X86IntelInstPrinter.c @@ -229,10 +229,10 @@ static void printRoundingControl(MCInst *MI, unsigned Op, SStream *O) { int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x3; switch (Imm) { - case 0: SStream_concat0(O, "{rn-sae}"); break; - case 1: SStream_concat0(O, "{rd-sae}"); break; - case 2: SStream_concat0(O, "{ru-sae}"); break; - case 3: SStream_concat0(O, "{rz-sae}"); break; + case 0: SStream_concat0(O, "{rn-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RN); break; + case 1: SStream_concat0(O, "{rd-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RD); break; + case 2: SStream_concat0(O, "{ru-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RU); break; + case 3: SStream_concat0(O, "{rz-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RZ); break; default: break; // never reach } } diff --git a/arch/X86/X86Mapping.c b/arch/X86/X86Mapping.c index fba182eb..6a8def80 100644 --- a/arch/X86/X86Mapping.c +++ b/arch/X86/X86Mapping.c @@ -42600,7 +42600,7 @@ void op_addAvxCC(MCInst *MI, int v) } } -void op_addZeroOpmask(MCInst *MI) +void op_addAvxZeroOpmask(MCInst *MI) { if (MI->csh->detail) { // link with the previous operand @@ -42608,4 +42608,18 @@ void op_addZeroOpmask(MCInst *MI) } } +void op_addAvxSae(MCInst *MI) +{ + if (MI->csh->detail) { + MI->flat_insn->detail->x86.avx_sae = true; + } +} + +void op_addAvxRoundingMode(MCInst *MI, int v) +{ + if (MI->csh->detail) { + MI->flat_insn->detail->x86.avx_rm = v; + } +} + #endif diff --git a/arch/X86/X86Mapping.h b/arch/X86/X86Mapping.h index 1e577bb2..17ba458e 100644 --- a/arch/X86/X86Mapping.h +++ b/arch/X86/X86Mapping.h @@ -52,6 +52,10 @@ void op_addAvxBroadcast(MCInst *MI, x86_avx_bcast v); void op_addSseCC(MCInst *MI, int v); void op_addAvxCC(MCInst *MI, int v); -void op_addZeroOpmask(MCInst *MI); +void op_addAvxZeroOpmask(MCInst *MI); + +void op_addAvxSae(MCInst *MI); + +void op_addAvxRoundingMode(MCInst *MI, int v); #endif diff --git a/bindings/java/TestX86.java b/bindings/java/TestX86.java index 0aec4002..b12cb0bc 100644 --- a/bindings/java/TestX86.java +++ b/bindings/java/TestX86.java @@ -73,6 +73,12 @@ public class TestX86 { if (operands.avxCC != 0) System.out.printf("\tavx_cc: %u\n", operands.avxCC); + if (operands.avxSae) + System.out.printf("\tavx_sae: TRUE\n"); + + if (operands.avxRm != 0) + System.out.printf("\tavx_rm: %u\n", operands.avxRm); + int count = ins.opCount(X86_OP_IMM); if (count > 0) { System.out.printf("\timm_count: %d\n", count); diff --git a/bindings/java/capstone/X86.java b/bindings/java/capstone/X86.java index c43fe20c..28f66a8a 100644 --- a/bindings/java/capstone/X86.java +++ b/bindings/java/capstone/X86.java @@ -78,6 +78,8 @@ public class X86 { public int sib_base; public int sse_cc; public int avx_cc; + public boolean avx_sae; + public int avx_rm; public char op_count; @@ -92,7 +94,7 @@ public class X86 { @Override public List getFieldOrder() { return Arrays.asList("prefix", "opcode", "addr_size", - "modrm", "sib", "disp", "sib_index", "sib_scale", "sib_base", "sse_cc", "avx_cc", "op_count", "op"); + "modrm", "sib", "disp", "sib_index", "sib_scale", "sib_base", "sse_cc", "avx_cc", "avx_sae", "avx_rm", "op_count", "op"); } } @@ -126,6 +128,8 @@ public class X86 { sibBase = e.sib_base; sseCC = e.sse_cc; avxCC = e.avx_cc; + avxSae = e.avx_sae; + avxRm = e.avx_rm; op = new Operand[e.op_count]; for (int i=0; i 0: print("\timm_count: %u" % count) diff --git a/include/x86.h b/include/x86.h index 2dc03954..50e0648f 100644 --- a/include/x86.h +++ b/include/x86.h @@ -141,6 +141,15 @@ typedef enum x86_avx_cc { X86_AVX_CC_TRUE_US, } x86_avx_cc; +//> AVX static rounding mode type +typedef enum x86_avx_rm { + X86_AVX_RM_INVALID = 0, // Uninitialized. + X86_AVX_RM_RN, // Round to nearest + X86_AVX_RM_RD, // Round down + X86_AVX_RM_RU, // Round up + X86_AVX_RM_RZ, // Round toward zero +} x86_avx_rm; + // Instruction's operand referring to memory // This is associated with X86_OP_MEM operand type above typedef struct x86_op_mem { @@ -208,6 +217,12 @@ typedef struct cs_x86 { // AVX Code Condition x86_avx_cc avx_cc; + // AVX Suppress all Exception + bool avx_sae; + + // AVX static rounding mode + x86_avx_rm avx_rm; + // Number of operands of this instruction, // or 0 when instruction has no operand. uint8_t op_count; diff --git a/tests/test_x86.c b/tests/test_x86.c index b1c53fed..280d5d54 100644 --- a/tests/test_x86.c +++ b/tests/test_x86.c @@ -60,14 +60,26 @@ static void print_insn_detail(csh ud, cs_mode mode, cs_insn *ins) printf("\t\tsib_scale: %d\n", x86->sib_scale); } + // SSE code condition if (x86->sse_cc != X86_SSE_CC_INVALID) { printf("\tsse_cc: %u\n", x86->sse_cc); } + // AVX code condition if (x86->avx_cc != X86_AVX_CC_INVALID) { printf("\tavx_cc: %u\n", x86->avx_cc); } + // AVX Suppress All Exception + if (x86->avx_sae) { + printf("\tavx_sae: %u\n", x86->avx_sae); + } + + // AVX Rounding Mode + if (x86->avx_rm != X86_AVX_RM_INVALID) { + printf("\tavx_rm: %u\n", x86->avx_rm); + } + count = cs_op_count(ud, ins, X86_OP_IMM); if (count) { printf("\timm_count: %u\n", count); @@ -114,8 +126,8 @@ static void print_insn_detail(csh ud, cs_mode mode, cs_insn *ins) printf("\t\toperands[%u].avx_bcast: %u\n", i, op->avx_bcast); // AVX zero opmask {z} - if (op->zero_opmask != false) - printf("\t\toperands[%u].zero_opmask: TRUE\n", i); + if (op->avx_zero_opmask != false) + printf("\t\toperands[%u].avx_zero_opmask: TRUE\n", i); printf("\t\toperands[%u].size: %u\n", i, op->size); }