From 21aae3ec898dcee5a6e5f0e46a15994762db74e8 Mon Sep 17 00:00:00 2001 From: NeverSightAI Date: Wed, 7 Oct 2026 04:29:02 -0700 Subject: [PATCH] fix(x86): keep GCC warning-clean feature builds --- arch/X86/X86Mapping.c | 1879 ++++++++++++++++-- tests/unit/x86_apx_cmov.c | 2 +- tests/unit/x86_apx_evex_convert.c | 113 +- tests/unit/x86_apx_evex_duplicate_prefix.c | 2 +- tests/unit/x86_apx_evex_invalidate.c | 69 +- tests/unit/x86_apx_evex_kmov.c | 148 +- tests/unit/x86_apx_evex_movrs.c | 94 +- tests/unit/x86_apx_setcc.c | 2 +- tests/unit/x86_evex_normalization_boundary.c | 8 +- tests/unit/x86_vex_legacy_prefix.c | 2 +- 10 files changed, 1996 insertions(+), 323 deletions(-) diff --git a/arch/X86/X86Mapping.c b/arch/X86/X86Mapping.c index 0e598057ba..b4926dd035 100644 --- a/arch/X86/X86Mapping.c +++ b/arch/X86/X86Mapping.c @@ -1785,61 +1785,379 @@ static x86_feature_decode_result decode_apx_adx(csh handle, return X86_FEATURE_DECODED; } -static x86_feature_decode_result decode_apx_unary(csh handle, - const uint8_t *code, size_t code_len, MCInst *instr, uint16_t *size) -{ - const cs_struct *arch=(const cs_struct *)(uintptr_t)handle; const uint8_t *e; - size_t off=0; uint8_t segp=0,p0,p1,p2,op,m,w,pp,group; bool a32=false,bad=false,mem,nd,nf; - unsigned n,ndn,feature; x86_reg r=X86_REG_INVALID,d=X86_REG_INVALID,seg; x86_feature_memory memory; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==code_len||code_len-off<2||(code[off+1]&7)!=4)return X86_FEATURE_NOT_HANDLED; - if(code_len-off<5)return X86_FEATURE_INVALID;e=&code[off];op=e[4];if(op!=0xfe&&op!=0xff&&op!=0xf6&&op!=0xf7)return X86_FEATURE_NOT_HANDLED; - if(!(arch->mode&CS_MODE_64)||bad||code_len-off<6||off+6>15)return X86_FEATURE_INVALID; - p0=e[1];p1=e[2];p2=e[3];m=e[5];pp=p1&3;group=(m>>3)&7;mem=(m&0xc0)!=0xc0;nd=(p2&0x10)!=0;nf=(p2&4)!=0; - if((p2&0xe3)!=0||pp>1||(!mem&&!(p1&4)))return X86_FEATURE_INVALID; - if(op==0xfe||op==0xff){if(group>1)return X86_FEATURE_NOT_HANDLED;feature=group?X86_FEATURE_APX_DEC:X86_FEATURE_APX_INC;} - else {if(group!=2&&group!=3&&group!=4&&group!=5&&group!=6&&group!=7)return X86_FEATURE_NOT_HANDLED;feature=group==2?X86_FEATURE_APX_NOT:group==3?X86_FEATURE_APX_NEG:group==4?X86_FEATURE_APX_MUL:group==5?X86_FEATURE_APX_IMUL_ONE:group==6?X86_FEATURE_APX_DIV:X86_FEATURE_APX_IDIV;if(feature==X86_FEATURE_APX_NOT&&nf)return X86_FEATURE_INVALID;if(group>=4&&nd)return X86_FEATURE_INVALID;} - if((op==0xfe||op==0xf6)){if(pp)return X86_FEATURE_INVALID;w=1;}else w=(p1&0x80)?8:pp?2:4; - ndn=((~p2&8)<<1)|((~p1&0x78)>>3);if(!nd&&ndn)return X86_FEATURE_INVALID; - if(nd){d=rex2_register(ndn,w);if(d==X86_REG_INVALID)return X86_FEATURE_INVALID;} - MCInst_clear(instr);MCInst_setOpcode(instr,feature);MCOperand_CreateImm0(instr,d);MCOperand_CreateImm0(instr,mem); - if(!mem){n=((~p0&0x20)>>2)|((p0&8)<<1)|(m&7);r=rex2_register(n,w);if(r==X86_REG_INVALID)return X86_FEATURE_INVALID;MCOperand_CreateImm0(instr,r);MCOperand_CreateImm0(instr,w);MCOperand_CreateImm0(instr,nd);MCOperand_CreateImm0(instr,nf);*size=(uint16_t)(off+6);set_apx_evex_encoding_detail(instr,e,off,segp,a32,NULL);return X86_FEATURE_DECODED;} - if(!decode_apx_evex_memory(code,code_len,off+5,p0,p1,a32,&memory))return X86_FEATURE_INVALID; - seg=apx_segment_register(segp);add_feature_memory_operands(instr,&memory);MCOperand_CreateImm0(instr,seg);MCOperand_CreateImm0(instr,a32?4:8);MCOperand_CreateImm0(instr,w);MCOperand_CreateImm0(instr,nd);MCOperand_CreateImm0(instr,nf);*size=(uint16_t)memory.length;set_apx_evex_encoding_detail(instr,e,off,segp,a32,&memory);return X86_FEATURE_DECODED; -} - -static x86_feature_decode_result decode_apx_bmi_ternary(csh handle,const uint8_t *code,size_t len,MCInst *instr,uint16_t *size) -{ - const cs_struct *arch=(const cs_struct *)(uintptr_t)handle;const uint8_t *e;size_t off=0;uint8_t segp=0,p0,p1,p2,op,m,w;bool a32=false,bad=false,mem,nf;x86_reg dst,s1,s2=X86_REG_INVALID,seg;unsigned dn,sn,rn,feature;x86_feature_memory memory; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=2)return X86_FEATURE_NOT_HANDLED;if(len-off<5)return X86_FEATURE_INVALID;e=&code[off];op=e[4];if(op!=0xf2&&op!=0xf5)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||len-off<6||off+6>15)return X86_FEATURE_INVALID; - p0=e[1];p1=e[2];p2=e[3];m=e[5];mem=(m&0xc0)!=0xc0;nf=(p2&4)!=0;if((p1&3)!=0||(p2&0xf3)!=0||(!mem&&!(p1&4)))return X86_FEATURE_INVALID;/* ND=0, LL=0, zeroing=0; memory U is inverted X4. */ - w=(p1&0x80)?8:4;feature=op==0xf2?X86_FEATURE_APX_ANDN:X86_FEATURE_APX_BZHI;dn=((~p0&0x80)>>4)|(~p0&0x10)|((m>>3)&7);sn=((~p2&8)<<1)|((~p1&0x78)>>3);dst=rex2_register(dn,w);s1=rex2_register(sn,w);if(dst==X86_REG_INVALID||s1==X86_REG_INVALID)return X86_FEATURE_INVALID; - MCInst_clear(instr);MCInst_setOpcode(instr,feature);MCOperand_CreateImm0(instr,s1);MCOperand_CreateImm0(instr,dst);MCOperand_CreateImm0(instr,mem); - if(!mem){rn=((~p0&0x20)>>2)|((p0&8)<<1)|(m&7);s2=rex2_register(rn,w);if(s2==X86_REG_INVALID)return X86_FEATURE_INVALID;MCOperand_CreateImm0(instr,s2);MCOperand_CreateImm0(instr,w);MCOperand_CreateImm0(instr,1);MCOperand_CreateImm0(instr,nf);*size=(uint16_t)(off+6);set_apx_evex_encoding_detail(instr,e,off,segp,a32,NULL);return X86_FEATURE_DECODED;} - if(!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&memory))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);add_feature_memory_operands(instr,&memory);MCOperand_CreateImm0(instr,seg);MCOperand_CreateImm0(instr,a32?4:8);MCOperand_CreateImm0(instr,w);MCOperand_CreateImm0(instr,1);MCOperand_CreateImm0(instr,nf);*size=(uint16_t)memory.length;set_apx_evex_encoding_detail(instr,e,off,segp,a32,&memory);return X86_FEATURE_DECODED; -} - -static x86_feature_decode_result decode_apx_pdep_pext(csh handle,const uint8_t *code,size_t len,MCInst *instr,uint16_t *size) -{ - const cs_struct *arch=(const cs_struct *)(uintptr_t)handle;const uint8_t*e;size_t off=0;uint8_t segp=0,p0,p1,p2,m,w,pp;bool a32=false,bad=false,mem;x86_reg dst,s1,s2=X86_REG_INVALID,seg;unsigned dn,sn,rn;x86_feature_memory mm; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=2)return X86_FEATURE_NOT_HANDLED;if(len-off<5)return X86_FEATURE_INVALID;e=&code[off];if(e[4]!=0xf5)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||len-off<6||off+6>15)return X86_FEATURE_INVALID; - p0=e[1];p1=e[2];p2=e[3];m=e[5];pp=p1&3;if(pp!=2&&pp!=3)return X86_FEATURE_NOT_HANDLED;mem=(m&0xc0)!=0xc0;if((p2&0xf7)!=0||(!mem&&!(p1&4)))return X86_FEATURE_INVALID;w=(p1&0x80)?8:4;dn=((~p0&0x80)>>4)|(~p0&0x10)|((m>>3)&7);sn=((~p2&8)<<1)|((~p1&0x78)>>3);dst=rex2_register(dn,w);s1=rex2_register(sn,w);if(dst==X86_REG_INVALID||s1==X86_REG_INVALID)return X86_FEATURE_INVALID; - MCInst_clear(instr);MCInst_setOpcode(instr,pp==3?X86_FEATURE_APX_PDEP:X86_FEATURE_APX_PEXT);MCOperand_CreateImm0(instr,dst);MCOperand_CreateImm0(instr,s1);MCOperand_CreateImm0(instr,mem); - if(!mem){rn=((~p0&0x20)>>2)|((p0&8)<<1)|(m&7);s2=rex2_register(rn,w);if(s2==X86_REG_INVALID)return X86_FEATURE_INVALID;MCOperand_CreateImm0(instr,s2);MCOperand_CreateImm0(instr,w);MCOperand_CreateImm0(instr,0);*size=(uint16_t)(off+6);set_apx_evex_encoding_detail(instr,e,off,segp,a32,NULL);return X86_FEATURE_DECODED;} - if(!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&mm))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);add_feature_memory_operands(instr,&mm);MCOperand_CreateImm0(instr,seg);MCOperand_CreateImm0(instr,a32?4:8);MCOperand_CreateImm0(instr,w);MCOperand_CreateImm0(instr,0);*size=(uint16_t)mm.length;set_apx_evex_encoding_detail(instr,e,off,segp,a32,&mm);return X86_FEATURE_DECODED; +static x86_feature_decode_result +decode_apx_unary(csh handle, const uint8_t *code, size_t code_len, + MCInst *instr, uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0; + uint8_t segp = 0, p0, p1, p2, op, m, w, pp, group; + bool a32 = false, bad = false, mem, nd, nf; + unsigned n, ndn, feature; + x86_reg r = X86_REG_INVALID, d = X86_REG_INVALID, seg; + x86_feature_memory memory; + while (off < code_len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, code_len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == code_len || code_len - off < 2 || (code[off + 1] & 7) != 4) + return X86_FEATURE_NOT_HANDLED; + if (code_len - off < 5) + return X86_FEATURE_INVALID; + e = &code[off]; + op = e[4]; + if (op != 0xfe && op != 0xff && op != 0xf6 && op != 0xf7) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || code_len - off < 6 || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + pp = p1 & 3; + group = (m >> 3) & 7; + mem = (m & 0xc0) != 0xc0; + nd = (p2 & 0x10) != 0; + nf = (p2 & 4) != 0; + if ((p2 & 0xe3) != 0 || pp > 1 || (!mem && !(p1 & 4))) + return X86_FEATURE_INVALID; + if (op == 0xfe || op == 0xff) { + if (group > 1) + return X86_FEATURE_NOT_HANDLED; + feature = group ? X86_FEATURE_APX_DEC : X86_FEATURE_APX_INC; + } else { + if (group != 2 && group != 3 && group != 4 && group != 5 && group != 6 && + group != 7) + return X86_FEATURE_NOT_HANDLED; + feature = group == 2 ? X86_FEATURE_APX_NOT + : group == 3 ? X86_FEATURE_APX_NEG + : group == 4 ? X86_FEATURE_APX_MUL + : group == 5 ? X86_FEATURE_APX_IMUL_ONE + : group == 6 ? X86_FEATURE_APX_DIV + : X86_FEATURE_APX_IDIV; + if (feature == X86_FEATURE_APX_NOT && nf) + return X86_FEATURE_INVALID; + if (group >= 4 && nd) + return X86_FEATURE_INVALID; + } + if ((op == 0xfe || op == 0xf6)) { + if (pp) + return X86_FEATURE_INVALID; + w = 1; + } else + w = (p1 & 0x80) ? 8 : pp ? 2 : 4; + ndn = ((~p2 & 8) << 1) | ((~p1 & 0x78) >> 3); + if (!nd && ndn) + return X86_FEATURE_INVALID; + if (nd) { + d = rex2_register(ndn, w); + if (d == X86_REG_INVALID) + return X86_FEATURE_INVALID; + } + MCInst_clear(instr); + MCInst_setOpcode(instr, feature); + MCOperand_CreateImm0(instr, d); + MCOperand_CreateImm0(instr, mem); + if (!mem) { + n = ((~p0 & 0x20) >> 2) | ((p0 & 8) << 1) | (m & 7); + r = rex2_register(n, w); + if (r == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCOperand_CreateImm0(instr, r); + MCOperand_CreateImm0(instr, w); + MCOperand_CreateImm0(instr, nd); + MCOperand_CreateImm0(instr, nf); + *size = (uint16_t)(off + 6); + set_apx_evex_encoding_detail(instr, e, off, segp, a32, NULL); + return X86_FEATURE_DECODED; + } + if (!decode_apx_evex_memory(code, code_len, off + 5, p0, p1, a32, &memory)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + add_feature_memory_operands(instr, &memory); + MCOperand_CreateImm0(instr, seg); + MCOperand_CreateImm0(instr, a32 ? 4 : 8); + MCOperand_CreateImm0(instr, w); + MCOperand_CreateImm0(instr, nd); + MCOperand_CreateImm0(instr, nf); + *size = (uint16_t)memory.length; + set_apx_evex_encoding_detail(instr, e, off, segp, a32, &memory); + return X86_FEATURE_DECODED; } -static x86_feature_decode_result decode_apx_double_shift(csh handle,const uint8_t*code,size_t len,MCInst*in,uint16_t*size) -{ - const cs_struct*arch=(const cs_struct*)(uintptr_t)handle;const uint8_t*e;size_t off=0,io;uint8_t segp=0,p0,p1,p2,op,m,pp,w,imm=0;bool a32=false,bad=false,mem,nd,nf,cl;x86_reg dst=X86_REG_INVALID,src,rm=X86_REG_INVALID,seg;unsigned dn,sn,rn;x86_feature_memory mm; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=4)return X86_FEATURE_NOT_HANDLED;if(len-off<5)return X86_FEATURE_INVALID;e=&code[off];op=e[4];if(op!=0x24&&op!=0x2c&&op!=0xa5&&op!=0xad)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||len-off<6||off+6>15)return X86_FEATURE_INVALID; - p0=e[1];p1=e[2];p2=e[3];m=e[5];pp=p1&3;mem=(m&0xc0)!=0xc0;nd=(p2&0x10)!=0;nf=(p2&4)!=0;cl=op>=0xa5;if(pp>1||(p2&0xe3)!=0||(!mem&&!(p1&4)))return X86_FEATURE_INVALID;w=(p1&0x80)?8:(pp?2:4);dn=((~p2&8)<<1)|((~p1&0x78)>>3);if(!nd&&dn)return X86_FEATURE_INVALID;if(nd){dst=rex2_register(dn,w);if(dst==X86_REG_INVALID)return X86_FEATURE_INVALID;}sn=((~p0&0x80)>>4)|(~p0&0x10)|((m>>3)&7);src=rex2_register(sn,w);if(src==X86_REG_INVALID)return X86_FEATURE_INVALID; - MCInst_clear(in);MCInst_setOpcode(in,(op==0x24||op==0xa5)?X86_FEATURE_APX_SHLD:X86_FEATURE_APX_SHRD);MCOperand_CreateImm0(in,dst);MCOperand_CreateImm0(in,src);MCOperand_CreateImm0(in,mem);MCOperand_CreateImm0(in,nd);MCOperand_CreateImm0(in,nf); - if(!mem){rn=((~p0&0x20)>>2)|((p0&8)<<1)|(m&7);rm=rex2_register(rn,w);if(rm==X86_REG_INVALID)return X86_FEATURE_INVALID;MCOperand_CreateImm0(in,rm);io=off+6;}else{if(!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&mm))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);add_feature_memory_operands(in,&mm);MCOperand_CreateImm0(in,seg);MCOperand_CreateImm0(in,a32?4:8);io=mm.length;} - if(!cl){if(io>=len||io>=15)return X86_FEATURE_INVALID;imm=code[io++];in->imm_size=1;}MCOperand_CreateImm0(in,w);MCOperand_CreateImm0(in,cl);MCOperand_CreateImm0(in,imm);*size=(uint16_t)io;set_apx_evex_encoding_detail(in,e,off,segp,a32,mem?&mm:NULL);if(!cl&&in->flat_insn->detail){in->flat_insn->detail->x86.encoding.imm_offset=(uint8_t)(io-1);in->flat_insn->detail->x86.encoding.imm_size=1;}return X86_FEATURE_DECODED; +static x86_feature_decode_result +decode_apx_bmi_ternary(csh handle, const uint8_t *code, size_t len, + MCInst *instr, uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0; + uint8_t segp = 0, p0, p1, p2, op, m, w; + bool a32 = false, bad = false, mem, nf; + x86_reg dst, s1, s2 = X86_REG_INVALID, seg; + unsigned dn, sn, rn, feature; + x86_feature_memory memory; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 2) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 5) + return X86_FEATURE_INVALID; + e = &code[off]; + op = e[4]; + if (op != 0xf2 && op != 0xf5) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || len - off < 6 || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + mem = (m & 0xc0) != 0xc0; + nf = (p2 & 4) != 0; + if ((p1 & 3) != 0 || (p2 & 0xf3) != 0 || (!mem && !(p1 & 4))) + return X86_FEATURE_INVALID; /* ND=0, LL=0, zeroing=0; memory U is inverted + X4. */ + w = (p1 & 0x80) ? 8 : 4; + feature = op == 0xf2 ? X86_FEATURE_APX_ANDN : X86_FEATURE_APX_BZHI; + dn = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | ((m >> 3) & 7); + sn = ((~p2 & 8) << 1) | ((~p1 & 0x78) >> 3); + dst = rex2_register(dn, w); + s1 = rex2_register(sn, w); + if (dst == X86_REG_INVALID || s1 == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCInst_clear(instr); + MCInst_setOpcode(instr, feature); + MCOperand_CreateImm0(instr, s1); + MCOperand_CreateImm0(instr, dst); + MCOperand_CreateImm0(instr, mem); + if (!mem) { + rn = ((~p0 & 0x20) >> 2) | ((p0 & 8) << 1) | (m & 7); + s2 = rex2_register(rn, w); + if (s2 == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCOperand_CreateImm0(instr, s2); + MCOperand_CreateImm0(instr, w); + MCOperand_CreateImm0(instr, 1); + MCOperand_CreateImm0(instr, nf); + *size = (uint16_t)(off + 6); + set_apx_evex_encoding_detail(instr, e, off, segp, a32, NULL); + return X86_FEATURE_DECODED; + } + if (!decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &memory)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + add_feature_memory_operands(instr, &memory); + MCOperand_CreateImm0(instr, seg); + MCOperand_CreateImm0(instr, a32 ? 4 : 8); + MCOperand_CreateImm0(instr, w); + MCOperand_CreateImm0(instr, 1); + MCOperand_CreateImm0(instr, nf); + *size = (uint16_t)memory.length; + set_apx_evex_encoding_detail(instr, e, off, segp, a32, &memory); + return X86_FEATURE_DECODED; +} + +static x86_feature_decode_result decode_apx_pdep_pext(csh handle, + const uint8_t *code, + size_t len, MCInst *instr, + uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0; + uint8_t segp = 0, p0, p1, p2, m, w, pp; + bool a32 = false, bad = false, mem; + x86_reg dst, s1, s2 = X86_REG_INVALID, seg; + unsigned dn, sn, rn; + x86_feature_memory mm; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 2) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 5) + return X86_FEATURE_INVALID; + e = &code[off]; + if (e[4] != 0xf5) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || len - off < 6 || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + pp = p1 & 3; + if (pp != 2 && pp != 3) + return X86_FEATURE_NOT_HANDLED; + mem = (m & 0xc0) != 0xc0; + if ((p2 & 0xf7) != 0 || (!mem && !(p1 & 4))) + return X86_FEATURE_INVALID; + w = (p1 & 0x80) ? 8 : 4; + dn = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | ((m >> 3) & 7); + sn = ((~p2 & 8) << 1) | ((~p1 & 0x78) >> 3); + dst = rex2_register(dn, w); + s1 = rex2_register(sn, w); + if (dst == X86_REG_INVALID || s1 == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCInst_clear(instr); + MCInst_setOpcode(instr, + pp == 3 ? X86_FEATURE_APX_PDEP : X86_FEATURE_APX_PEXT); + MCOperand_CreateImm0(instr, dst); + MCOperand_CreateImm0(instr, s1); + MCOperand_CreateImm0(instr, mem); + if (!mem) { + rn = ((~p0 & 0x20) >> 2) | ((p0 & 8) << 1) | (m & 7); + s2 = rex2_register(rn, w); + if (s2 == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCOperand_CreateImm0(instr, s2); + MCOperand_CreateImm0(instr, w); + MCOperand_CreateImm0(instr, 0); + *size = (uint16_t)(off + 6); + set_apx_evex_encoding_detail(instr, e, off, segp, a32, NULL); + return X86_FEATURE_DECODED; + } + if (!decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &mm)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + add_feature_memory_operands(instr, &mm); + MCOperand_CreateImm0(instr, seg); + MCOperand_CreateImm0(instr, a32 ? 4 : 8); + MCOperand_CreateImm0(instr, w); + MCOperand_CreateImm0(instr, 0); + *size = (uint16_t)mm.length; + set_apx_evex_encoding_detail(instr, e, off, segp, a32, &mm); + return X86_FEATURE_DECODED; +} + +static x86_feature_decode_result decode_apx_double_shift(csh handle, + const uint8_t *code, + size_t len, MCInst *in, + uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0, io; + uint8_t segp = 0, p0, p1, p2, op, m, pp, w, imm = 0; + bool a32 = false, bad = false, mem, nd, nf, cl; + x86_reg dst = X86_REG_INVALID, src, rm = X86_REG_INVALID, seg; + unsigned dn, sn, rn; + x86_feature_memory mm; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 4) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 5) + return X86_FEATURE_INVALID; + e = &code[off]; + op = e[4]; + if (op != 0x24 && op != 0x2c && op != 0xa5 && op != 0xad) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || len - off < 6 || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + pp = p1 & 3; + mem = (m & 0xc0) != 0xc0; + nd = (p2 & 0x10) != 0; + nf = (p2 & 4) != 0; + cl = op >= 0xa5; + if (pp > 1 || (p2 & 0xe3) != 0 || (!mem && !(p1 & 4))) + return X86_FEATURE_INVALID; + w = (p1 & 0x80) ? 8 : (pp ? 2 : 4); + dn = ((~p2 & 8) << 1) | ((~p1 & 0x78) >> 3); + if (!nd && dn) + return X86_FEATURE_INVALID; + if (nd) { + dst = rex2_register(dn, w); + if (dst == X86_REG_INVALID) + return X86_FEATURE_INVALID; + } + sn = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | ((m >> 3) & 7); + src = rex2_register(sn, w); + if (src == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCInst_clear(in); + MCInst_setOpcode(in, (op == 0x24 || op == 0xa5) ? X86_FEATURE_APX_SHLD + : X86_FEATURE_APX_SHRD); + MCOperand_CreateImm0(in, dst); + MCOperand_CreateImm0(in, src); + MCOperand_CreateImm0(in, mem); + MCOperand_CreateImm0(in, nd); + MCOperand_CreateImm0(in, nf); + if (!mem) { + rn = ((~p0 & 0x20) >> 2) | ((p0 & 8) << 1) | (m & 7); + rm = rex2_register(rn, w); + if (rm == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCOperand_CreateImm0(in, rm); + io = off + 6; + } else { + if (!decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &mm)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + add_feature_memory_operands(in, &mm); + MCOperand_CreateImm0(in, seg); + MCOperand_CreateImm0(in, a32 ? 4 : 8); + io = mm.length; + } + if (!cl) { + if (io >= len || io >= 15) + return X86_FEATURE_INVALID; + imm = code[io++]; + in->imm_size = 1; + } + MCOperand_CreateImm0(in, w); + MCOperand_CreateImm0(in, cl); + MCOperand_CreateImm0(in, imm); + *size = (uint16_t)io; + set_apx_evex_encoding_detail(in, e, off, segp, a32, mem ? &mm : NULL); + if (!cl && in->flat_insn->detail) { + in->flat_insn->detail->x86.encoding.imm_offset = (uint8_t)(io - 1); + in->flat_insn->detail->x86.encoding.imm_size = 1; + } + return X86_FEATURE_DECODED; } static x86_feature_decode_result @@ -1983,12 +2301,81 @@ decode_legacy_cet_store(csh handle, const uint8_t *code, size_t code_len, return X86_FEATURE_DECODED; } -static x86_feature_decode_result decode_apx_direct_store(csh handle,const uint8_t*code,size_t len,MCInst*in,uint16_t*size) -{ - const cs_struct*arch=(const cs_struct*)(uintptr_t)handle;const uint8_t*e;size_t off=0;uint8_t segp=0,p0,p1,p2,op,m,pp,w;bool a32=false,bad=false;x86_reg src,seg;unsigned sn,feature;x86_feature_memory mm; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=4)return X86_FEATURE_NOT_HANDLED;if(len-off<5)return X86_FEATURE_INVALID;e=&code[off];op=e[4];if(op!=0xf9&&op!=0x66&&op!=0x65)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||len-off<6||off+6>15)return X86_FEATURE_INVALID;p0=e[1];p1=e[2];p2=e[3];m=e[5];pp=p1&3;if(op==0x66&&pp!=0)return X86_FEATURE_NOT_HANDLED;if((m&0xc0)==0xc0||(p1&0x78)!=0x78||p2!=8)return X86_FEATURE_INVALID; - if(op==0xf9){if(pp)return X86_FEATURE_INVALID;feature=X86_FEATURE_APX_MOVDIRI;}else if(op==0x66){if(pp)return X86_FEATURE_INVALID;feature=(p1&0x80)?X86_FEATURE_APX_WRSSQ:X86_FEATURE_APX_WRSSD;}else{if(pp!=1)return X86_FEATURE_INVALID;feature=(p1&0x80)?X86_FEATURE_APX_WRUSSQ:X86_FEATURE_APX_WRUSSD;}w=(p1&0x80)?8:4;sn=((~p0&0x80)>>4)|(~p0&0x10)|((m>>3)&7);src=rex2_register(sn,w);if(src==X86_REG_INVALID)return X86_FEATURE_INVALID;if(!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&mm))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);MCInst_clear(in);MCInst_setOpcode(in,feature);MCOperand_CreateImm0(in,src);add_feature_memory_operands(in,&mm);MCOperand_CreateImm0(in,seg);MCOperand_CreateImm0(in,a32?4:8);MCOperand_CreateImm0(in,w);*size=(uint16_t)mm.length;set_apx_evex_encoding_detail(in,e,off,segp,a32,&mm);return X86_FEATURE_DECODED; +static x86_feature_decode_result decode_apx_direct_store(csh handle, + const uint8_t *code, + size_t len, MCInst *in, + uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0; + uint8_t segp = 0, p0, p1, p2, op, m, pp, w; + bool a32 = false, bad = false; + x86_reg src, seg; + unsigned sn, feature; + x86_feature_memory mm; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 4) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 5) + return X86_FEATURE_INVALID; + e = &code[off]; + op = e[4]; + if (op != 0xf9 && op != 0x66 && op != 0x65) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || len - off < 6 || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + pp = p1 & 3; + if (op == 0x66 && pp != 0) + return X86_FEATURE_NOT_HANDLED; + if ((m & 0xc0) == 0xc0 || (p1 & 0x78) != 0x78 || p2 != 8) + return X86_FEATURE_INVALID; + if (op == 0xf9) { + if (pp) + return X86_FEATURE_INVALID; + feature = X86_FEATURE_APX_MOVDIRI; + } else if (op == 0x66) { + if (pp) + return X86_FEATURE_INVALID; + feature = (p1 & 0x80) ? X86_FEATURE_APX_WRSSQ : X86_FEATURE_APX_WRSSD; + } else { + if (pp != 1) + return X86_FEATURE_INVALID; + feature = (p1 & 0x80) ? X86_FEATURE_APX_WRUSSQ : X86_FEATURE_APX_WRUSSD; + } + w = (p1 & 0x80) ? 8 : 4; + sn = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | ((m >> 3) & 7); + src = rex2_register(sn, w); + if (src == X86_REG_INVALID) + return X86_FEATURE_INVALID; + if (!decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &mm)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + MCInst_clear(in); + MCInst_setOpcode(in, feature); + MCOperand_CreateImm0(in, src); + add_feature_memory_operands(in, &mm); + MCOperand_CreateImm0(in, seg); + MCOperand_CreateImm0(in, a32 ? 4 : 8); + MCOperand_CreateImm0(in, w); + *size = (uint16_t)mm.length; + set_apx_evex_encoding_detail(in, e, off, segp, a32, &mm); + return X86_FEATURE_DECODED; } static x86_feature_decode_result @@ -2143,70 +2530,429 @@ static x86_feature_decode_result decode_apx_cmpccxadd(csh handle,const uint8_t*c const cs_struct*arch=(const cs_struct*)(uintptr_t)handle;const uint8_t*e;size_t off=0;uint8_t segp=0,p0,p1,p2,op,m,w;x86_reg cmp,add,seg;bool a32=false,bad=false;unsigned cn,an;x86_feature_memory mm;while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;}if(off==len||len-off<2||(code[off+1]&7)!=2)return X86_FEATURE_NOT_HANDLED;if(len-off<5)return X86_FEATURE_INVALID;e=&code[off];op=e[4];if(op<0xe0||op>0xef)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||len-off<6||off+6>15)return X86_FEATURE_INVALID;p0=e[1];p1=e[2];p2=e[3];m=e[5];if((p1&3)!=1||(m&0xc0)==0xc0||(p2&0xf7)!=0)return X86_FEATURE_INVALID;w=(p1&0x80)?8:4;cn=((~p0&0x80)>>4)|(~p0&0x10)|((m>>3)&7);an=((~p2&8)<<1)|((~p1&0x78)>>3);cmp=rex2_register(cn,w);add=rex2_register(an,w);if(cmp==X86_REG_INVALID||add==X86_REG_INVALID||!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&mm))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);MCInst_clear(in);MCInst_setOpcode(in,X86_FEATURE_APX_CMPCCXADD_BASE+(op-0xe0));MCOperand_CreateImm0(in,cmp);MCOperand_CreateImm0(in,add);add_feature_memory_operands(in,&mm);MCOperand_CreateImm0(in,seg);MCOperand_CreateImm0(in,a32?4:8);MCOperand_CreateImm0(in,w);*size=(uint16_t)mm.length;set_apx_evex_encoding_detail(in,e,off,segp,a32,&mm);return X86_FEATURE_DECODED; } -static x86_feature_decode_result decode_apx_ccmp(csh handle,const uint8_t*code,size_t len,MCInst*in,uint16_t*size) -{ - const cs_struct*arch=(const cs_struct*)(uintptr_t)handle;const uint8_t*e;size_t off=0,io;uint8_t segp=0,p0,p1,p2,op,m,w,dfv,imm_size=0;bool a32=false,bad=false,mem,imm=false,rm_first=true;x86_reg rr=X86_REG_INVALID,rm=X86_REG_INVALID,seg=X86_REG_INVALID;unsigned rn;int64_t iv=0;x86_feature_memory mm; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=4)return X86_FEATURE_NOT_HANDLED;if(len-off<6)return X86_FEATURE_INVALID;e=&code[off];op=e[4];if(op!=0x38&&op!=0x39&&op!=0x3a&&op!=0x3b&&op!=0x80&&op!=0x81&&op!=0x83)return X86_FEATURE_NOT_HANDLED; - /* Of the immediate group only /7 is CCMP; /0../6 are the ALU forms. */ - if (op >= 0x80 && ((e[5] >> 3) & 7) != 7) - return X86_FEATURE_NOT_HANDLED; - if(!(arch->mode&CS_MODE_64)||bad||off+6>15)return X86_FEATURE_INVALID;p0=e[1];p1=e[2];p2=e[3];m=e[5];mem=(m&0xc0)!=0xc0;dfv=(p1>>3)&15; - /* SCC occupies all of P2; ND, NF, zeroing, VL and EVEX.b are reserved here. */ - if(p2&0xf0)return X86_FEATURE_INVALID; - /* As in the other promoted ALU forms, byte forms ignore W, and W - * selects 64-bit operands over a 66 prefix. */ - if(!mem&&!(p1&4))return X86_FEATURE_INVALID;if(op==0x38||op==0x3a||op==0x80){if((p1&3)!=0)return X86_FEATURE_INVALID;w=1;}else{if((p1&3)>1)return X86_FEATURE_INVALID;w=(p1&0x80)?8:(p1&1)?2:4;} - imm = op >= 0x80; - if (!imm) { - rn = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | ((m >> 3) & 7); - rr = rex2_register(rn, w); - if (rr == X86_REG_INVALID) - return X86_FEATURE_INVALID; - rm_first = op == 0x38 || op == 0x39; - } - MCInst_clear(in);MCInst_setOpcode(in,X86_FEATURE_APX_CCMP_BASE+(p2&15));MCOperand_CreateImm0(in,mem);MCOperand_CreateImm0(in,rm_first);MCOperand_CreateImm0(in,rr); - if(!mem){rn=((~p0&0x20)>>2)|((p0&8)<<1)|(m&7);rm=rex2_register(rn,w);if(rm==X86_REG_INVALID)return X86_FEATURE_INVALID;MCOperand_CreateImm0(in,rm);io=off+6;}else{if(!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&mm))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);add_feature_memory_operands(in,&mm);MCOperand_CreateImm0(in,seg);MCOperand_CreateImm0(in,a32?4:8);io=mm.length;} - if(imm){imm_size=op==0x81?(w==2?2:4):1;if(io+imm_size>len||io+imm_size>15)return X86_FEATURE_INVALID;if(imm_size==1)iv=w==1?(int64_t)code[io]:(int64_t)(int8_t)code[io];else if(imm_size==2)iv=(uint16_t)(code[io]|code[io+1]<<8);else{uint32_t raw=(uint32_t)code[io]|(uint32_t)code[io+1]<<8|(uint32_t)code[io+2]<<16|(uint32_t)code[io+3]<<24;iv=w==8?(int64_t)(int32_t)raw:(int64_t)raw;}io+=imm_size;in->imm_size=imm_size;} - MCOperand_CreateImm0(in,imm);MCOperand_CreateImm0(in,iv);MCOperand_CreateImm0(in,w);MCOperand_CreateImm0(in,dfv);*size=(uint16_t)io;set_apx_evex_encoding_detail(in,e,off,segp,a32,mem?&mm:NULL);if(in->flat_insn->detail&&imm){in->flat_insn->detail->x86.encoding.imm_offset=(uint8_t)(io-imm_size);in->flat_insn->detail->x86.encoding.imm_size=imm_size;}return X86_FEATURE_DECODED; -} - -static x86_feature_decode_result decode_apx_ctest(csh handle,const uint8_t*code,size_t len,MCInst*in,uint16_t*size) -{ - const cs_struct*arch=(const cs_struct*)(uintptr_t)handle;const uint8_t*e;size_t off=0,io;uint8_t segp=0,p0,p1,p2,op,m,w,dfv,imm_size=0;bool a32=false,bad=false,mem,imm;x86_reg rr=X86_REG_INVALID,rm=X86_REG_INVALID,seg=X86_REG_INVALID;unsigned rn,group;int64_t iv=0;x86_feature_memory mm; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=4)return X86_FEATURE_NOT_HANDLED;if(len-off<6)return X86_FEATURE_INVALID;e=&code[off];op=e[4];if(op!=0x84&&op!=0x85&&op!=0xf6&&op!=0xf7)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||off+6>15)return X86_FEATURE_INVALID; - p0=e[1];p1=e[2];p2=e[3];m=e[5];mem=(m&0xc0)!=0xc0;imm=op==0xf6||op==0xf7;group=(m>>3)&7;if(imm&&group>1)return X86_FEATURE_NOT_HANDLED;dfv=(p1>>3)&15;if((p2&0xf0)||(!mem&&!(p1&4)))return X86_FEATURE_INVALID; - /* Byte forms ignore W; W selects 64-bit operands over a 66 prefix. */ - if(op==0x84||op==0xf6){if(p1&3)return X86_FEATURE_INVALID;w=1;}else{if((p1&3)>1)return X86_FEATURE_INVALID;w=(p1&0x80)?8:(p1&1)?2:4;} - if(!imm){rn=((~p0&0x80)>>4)|(~p0&0x10)|group;rr=rex2_register(rn,w);if(rr==X86_REG_INVALID)return X86_FEATURE_INVALID;} - MCInst_clear(in);MCInst_setOpcode(in,X86_FEATURE_APX_CTEST_BASE+(p2&15));MCOperand_CreateImm0(in,mem);MCOperand_CreateImm0(in,1);MCOperand_CreateImm0(in,rr); - if(!mem){rn=((~p0&0x20)>>2)|((p0&8)<<1)|(m&7);rm=rex2_register(rn,w);if(rm==X86_REG_INVALID)return X86_FEATURE_INVALID;MCOperand_CreateImm0(in,rm);io=off+6;}else{if(!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&mm))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);add_feature_memory_operands(in,&mm);MCOperand_CreateImm0(in,seg);MCOperand_CreateImm0(in,a32?4:8);io=mm.length;} - if(imm){imm_size=op==0xf7?(w==2?2:4):1;if(io+imm_size>len||io+imm_size>15)return X86_FEATURE_INVALID;if(imm_size==1)iv=w==1?(int64_t)code[io]:(int64_t)(int8_t)code[io];else if(imm_size==2)iv=(uint16_t)(code[io]|code[io+1]<<8);else{uint32_t raw=(uint32_t)code[io]|(uint32_t)code[io+1]<<8|(uint32_t)code[io+2]<<16|(uint32_t)code[io+3]<<24;iv=w==8?(int64_t)(int32_t)raw:(int64_t)raw;}io+=imm_size;in->imm_size=imm_size;} - MCOperand_CreateImm0(in,imm);MCOperand_CreateImm0(in,iv);MCOperand_CreateImm0(in,w);MCOperand_CreateImm0(in,dfv);*size=(uint16_t)io;set_apx_evex_encoding_detail(in,e,off,segp,a32,mem?&mm:NULL);if(in->flat_insn->detail&&imm){in->flat_insn->detail->x86.encoding.imm_offset=(uint8_t)(io-imm_size);in->flat_insn->detail->x86.encoding.imm_size=imm_size;}return X86_FEATURE_DECODED; -} - -static x86_feature_decode_result decode_apx_kmov(csh handle,const uint8_t*code,size_t len,MCInst*in,uint16_t*size) -{ - const cs_struct*arch=(const cs_struct*)(uintptr_t)handle;const uint8_t*e;size_t off=0;uint8_t segp=0,p0,p1,p2,op,m,pp,w,fi;bool a32=false,bad=false,mem;x86_reg reg,rm=X86_REG_INVALID,seg=X86_REG_INVALID;unsigned rn,mn;x86_feature_memory mm; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=1)return X86_FEATURE_NOT_HANDLED;if(len-off<6)return X86_FEATURE_INVALID;e=&code[off];op=e[4];if(op<0x90||op>0x93)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||off+6>15)return X86_FEATURE_INVALID; - p0=e[1];p1=e[2];p2=e[3];m=e[5];pp=p1&3;mem=(m&0xc0)!=0xc0;if((p1&0x78)!=0x78||(!mem&&!(p1&4))||p2!=8)return X86_FEATURE_INVALID; - if(op<=0x91){if(pp==1&&!(p1&0x80)){w=1;fi=0;}else if(pp==0&&!(p1&0x80)){w=2;fi=3;}else if(pp==1&&(p1&0x80)){w=4;fi=1;}else if(pp==0&&(p1&0x80)){w=8;fi=2;}else return X86_FEATURE_INVALID;}else{if(pp==1&&!(p1&0x80)){w=1;fi=0;}else if(pp==0&&!(p1&0x80)){w=2;fi=3;}else if(pp==3&&!(p1&0x80)){w=4;fi=1;}else if(pp==3&&(p1&0x80)){w=8;fi=2;}else return X86_FEATURE_INVALID;} - if((op==0x91&&!mem)||((op==0x92||op==0x93)&&mem))return X86_FEATURE_INVALID;rn=((~p0&0x80)>>4)|(~p0&0x10)|((m>>3)&7);mn=((~p0&0x20)>>2)|((p0&8)<<1)|(m&7); - if(op==0x93)reg=rex2_register(rn,w==8?8:4);else{if(rn>7)return X86_FEATURE_INVALID;reg=(x86_reg)(X86_REG_K0+rn);}if(reg==X86_REG_INVALID)return X86_FEATURE_INVALID; - MCInst_clear(in);MCInst_setOpcode(in,X86_FEATURE_APX_KMOV_BASE+fi);MCOperand_CreateImm0(in,op);MCOperand_CreateImm0(in,reg);MCOperand_CreateImm0(in,mem); - if(!mem){if(op==0x92)rm=rex2_register(mn,w==8?8:4);else{if(mn>7)return X86_FEATURE_INVALID;rm=(x86_reg)(X86_REG_K0+mn);}if(rm==X86_REG_INVALID)return X86_FEATURE_INVALID;MCOperand_CreateImm0(in,rm);MCOperand_CreateImm0(in,w);*size=(uint16_t)(off+6);set_apx_evex_encoding_detail(in,e,off,segp,a32,NULL);return X86_FEATURE_DECODED;} - if(!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&mm))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);add_feature_memory_operands(in,&mm);MCOperand_CreateImm0(in,seg);MCOperand_CreateImm0(in,a32?4:8);MCOperand_CreateImm0(in,w);*size=(uint16_t)mm.length;set_apx_evex_encoding_detail(in,e,off,segp,a32,&mm);return X86_FEATURE_DECODED; -} - -static x86_feature_decode_result decode_apx_movrs(csh handle,const uint8_t*code,size_t len,MCInst*in,uint16_t*size) -{ - const cs_struct*arch=(const cs_struct*)(uintptr_t)handle;const uint8_t*e;size_t off=0;uint8_t segp=0,p0,p1,p2,op,m,w;bool a32=false,bad=false;x86_reg dst,seg;unsigned rn;x86_feature_memory mm; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=4)return X86_FEATURE_NOT_HANDLED;if(len-off<6)return X86_FEATURE_INVALID;e=&code[off];op=e[4];if(op!=0x8a&&op!=0x8b)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||off+6>15)return X86_FEATURE_INVALID; - p0=e[1];p1=e[2];p2=e[3];m=e[5];if((m&0xc0)==0xc0||(p1&0x78)!=0x78||p2!=8)return X86_FEATURE_INVALID;if(op==0x8a){if(p1&0x83)return X86_FEATURE_INVALID;w=1;}else{if((p1&3)>1)return X86_FEATURE_INVALID;w=(p1&0x80)?8:(p1&1)?2:4;} - rn=((~p0&0x80)>>4)|(~p0&0x10)|((m>>3)&7);dst=rex2_register(rn,w);if(dst==X86_REG_INVALID||!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&mm))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);MCInst_clear(in);MCInst_setOpcode(in,X86_FEATURE_APX_MOVRS);MCOperand_CreateImm0(in,dst);add_feature_memory_operands(in,&mm);MCOperand_CreateImm0(in,seg);MCOperand_CreateImm0(in,a32?4:8);MCOperand_CreateImm0(in,w);*size=(uint16_t)mm.length;set_apx_evex_encoding_detail(in,e,off,segp,a32,&mm);return X86_FEATURE_DECODED; +static x86_feature_decode_result decode_apx_ccmp(csh handle, + const uint8_t *code, + size_t len, MCInst *in, + uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0, io; + uint8_t segp = 0, p0, p1, p2, op, m, w, dfv, imm_size = 0; + bool a32 = false, bad = false, mem, imm = false, rm_first = true; + x86_reg rr = X86_REG_INVALID, rm = X86_REG_INVALID, seg = X86_REG_INVALID; + unsigned rn; + int64_t iv = 0; + x86_feature_memory mm; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 4) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 6) + return X86_FEATURE_INVALID; + e = &code[off]; + op = e[4]; + if (op != 0x38 && op != 0x39 && op != 0x3a && op != 0x3b && op != 0x80 && + op != 0x81 && op != 0x83) + return X86_FEATURE_NOT_HANDLED; + /* Of the immediate group only /7 is CCMP; /0../6 are the ALU forms. */ + if (op >= 0x80 && ((e[5] >> 3) & 7) != 7) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + mem = (m & 0xc0) != 0xc0; + dfv = (p1 >> 3) & 15; + /* SCC occupies all of P2; ND, NF, zeroing, VL and EVEX.b are reserved here. + */ + if (p2 & 0xf0) + return X86_FEATURE_INVALID; + /* As in the other promoted ALU forms, byte forms ignore W, and W + * selects 64-bit operands over a 66 prefix. */ + if (!mem && !(p1 & 4)) + return X86_FEATURE_INVALID; + if (op == 0x38 || op == 0x3a || op == 0x80) { + if ((p1 & 3) != 0) + return X86_FEATURE_INVALID; + w = 1; + } else { + if ((p1 & 3) > 1) + return X86_FEATURE_INVALID; + w = (p1 & 0x80) ? 8 : (p1 & 1) ? 2 : 4; + } + imm = op >= 0x80; + if (!imm) { + rn = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | ((m >> 3) & 7); + rr = rex2_register(rn, w); + if (rr == X86_REG_INVALID) + return X86_FEATURE_INVALID; + rm_first = op == 0x38 || op == 0x39; + } + MCInst_clear(in); + MCInst_setOpcode(in, X86_FEATURE_APX_CCMP_BASE + (p2 & 15)); + MCOperand_CreateImm0(in, mem); + MCOperand_CreateImm0(in, rm_first); + MCOperand_CreateImm0(in, rr); + if (!mem) { + rn = ((~p0 & 0x20) >> 2) | ((p0 & 8) << 1) | (m & 7); + rm = rex2_register(rn, w); + if (rm == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCOperand_CreateImm0(in, rm); + io = off + 6; + } else { + if (!decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &mm)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + add_feature_memory_operands(in, &mm); + MCOperand_CreateImm0(in, seg); + MCOperand_CreateImm0(in, a32 ? 4 : 8); + io = mm.length; + } + if (imm) { + imm_size = op == 0x81 ? (w == 2 ? 2 : 4) : 1; + if (io + imm_size > len || io + imm_size > 15) + return X86_FEATURE_INVALID; + if (imm_size == 1) + iv = w == 1 ? (int64_t)code[io] : (int64_t)(int8_t)code[io]; + else if (imm_size == 2) + iv = (uint16_t)(code[io] | code[io + 1] << 8); + else { + uint32_t raw = (uint32_t)code[io] | (uint32_t)code[io + 1] << 8 | + (uint32_t)code[io + 2] << 16 | + (uint32_t)code[io + 3] << 24; + iv = w == 8 ? (int64_t)(int32_t)raw : (int64_t)raw; + } + io += imm_size; + in->imm_size = imm_size; + } + MCOperand_CreateImm0(in, imm); + MCOperand_CreateImm0(in, iv); + MCOperand_CreateImm0(in, w); + MCOperand_CreateImm0(in, dfv); + *size = (uint16_t)io; + set_apx_evex_encoding_detail(in, e, off, segp, a32, mem ? &mm : NULL); + if (in->flat_insn->detail && imm) { + in->flat_insn->detail->x86.encoding.imm_offset = (uint8_t)(io - imm_size); + in->flat_insn->detail->x86.encoding.imm_size = imm_size; + } + return X86_FEATURE_DECODED; +} + +static x86_feature_decode_result decode_apx_ctest(csh handle, + const uint8_t *code, + size_t len, MCInst *in, + uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0, io; + uint8_t segp = 0, p0, p1, p2, op, m, w, dfv, imm_size = 0; + bool a32 = false, bad = false, mem, imm; + x86_reg rr = X86_REG_INVALID, rm = X86_REG_INVALID, seg = X86_REG_INVALID; + unsigned rn, group; + int64_t iv = 0; + x86_feature_memory mm; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 4) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 6) + return X86_FEATURE_INVALID; + e = &code[off]; + op = e[4]; + if (op != 0x84 && op != 0x85 && op != 0xf6 && op != 0xf7) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + mem = (m & 0xc0) != 0xc0; + imm = op == 0xf6 || op == 0xf7; + group = (m >> 3) & 7; + if (imm && group > 1) + return X86_FEATURE_NOT_HANDLED; + dfv = (p1 >> 3) & 15; + if ((p2 & 0xf0) || (!mem && !(p1 & 4))) + return X86_FEATURE_INVALID; + /* Byte forms ignore W; W selects 64-bit operands over a 66 prefix. */ + if (op == 0x84 || op == 0xf6) { + if (p1 & 3) + return X86_FEATURE_INVALID; + w = 1; + } else { + if ((p1 & 3) > 1) + return X86_FEATURE_INVALID; + w = (p1 & 0x80) ? 8 : (p1 & 1) ? 2 : 4; + } + if (!imm) { + rn = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | group; + rr = rex2_register(rn, w); + if (rr == X86_REG_INVALID) + return X86_FEATURE_INVALID; + } + MCInst_clear(in); + MCInst_setOpcode(in, X86_FEATURE_APX_CTEST_BASE + (p2 & 15)); + MCOperand_CreateImm0(in, mem); + MCOperand_CreateImm0(in, 1); + MCOperand_CreateImm0(in, rr); + if (!mem) { + rn = ((~p0 & 0x20) >> 2) | ((p0 & 8) << 1) | (m & 7); + rm = rex2_register(rn, w); + if (rm == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCOperand_CreateImm0(in, rm); + io = off + 6; + } else { + if (!decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &mm)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + add_feature_memory_operands(in, &mm); + MCOperand_CreateImm0(in, seg); + MCOperand_CreateImm0(in, a32 ? 4 : 8); + io = mm.length; + } + if (imm) { + imm_size = op == 0xf7 ? (w == 2 ? 2 : 4) : 1; + if (io + imm_size > len || io + imm_size > 15) + return X86_FEATURE_INVALID; + if (imm_size == 1) + iv = w == 1 ? (int64_t)code[io] : (int64_t)(int8_t)code[io]; + else if (imm_size == 2) + iv = (uint16_t)(code[io] | code[io + 1] << 8); + else { + uint32_t raw = (uint32_t)code[io] | (uint32_t)code[io + 1] << 8 | + (uint32_t)code[io + 2] << 16 | + (uint32_t)code[io + 3] << 24; + iv = w == 8 ? (int64_t)(int32_t)raw : (int64_t)raw; + } + io += imm_size; + in->imm_size = imm_size; + } + MCOperand_CreateImm0(in, imm); + MCOperand_CreateImm0(in, iv); + MCOperand_CreateImm0(in, w); + MCOperand_CreateImm0(in, dfv); + *size = (uint16_t)io; + set_apx_evex_encoding_detail(in, e, off, segp, a32, mem ? &mm : NULL); + if (in->flat_insn->detail && imm) { + in->flat_insn->detail->x86.encoding.imm_offset = (uint8_t)(io - imm_size); + in->flat_insn->detail->x86.encoding.imm_size = imm_size; + } + return X86_FEATURE_DECODED; +} + +static x86_feature_decode_result decode_apx_kmov(csh handle, + const uint8_t *code, + size_t len, MCInst *in, + uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0; + uint8_t segp = 0, p0, p1, p2, op, m, pp, w, fi; + bool a32 = false, bad = false, mem; + x86_reg reg, rm = X86_REG_INVALID, seg = X86_REG_INVALID; + unsigned rn, mn; + x86_feature_memory mm; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 1) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 6) + return X86_FEATURE_INVALID; + e = &code[off]; + op = e[4]; + if (op < 0x90 || op > 0x93) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + pp = p1 & 3; + mem = (m & 0xc0) != 0xc0; + if ((p1 & 0x78) != 0x78 || (!mem && !(p1 & 4)) || p2 != 8) + return X86_FEATURE_INVALID; + if (op <= 0x91) { + if (pp == 1 && !(p1 & 0x80)) { + w = 1; + fi = 0; + } else if (pp == 0 && !(p1 & 0x80)) { + w = 2; + fi = 3; + } else if (pp == 1 && (p1 & 0x80)) { + w = 4; + fi = 1; + } else if (pp == 0 && (p1 & 0x80)) { + w = 8; + fi = 2; + } else + return X86_FEATURE_INVALID; + } else { + if (pp == 1 && !(p1 & 0x80)) { + w = 1; + fi = 0; + } else if (pp == 0 && !(p1 & 0x80)) { + w = 2; + fi = 3; + } else if (pp == 3 && !(p1 & 0x80)) { + w = 4; + fi = 1; + } else if (pp == 3 && (p1 & 0x80)) { + w = 8; + fi = 2; + } else + return X86_FEATURE_INVALID; + } + if ((op == 0x91 && !mem) || ((op == 0x92 || op == 0x93) && mem)) + return X86_FEATURE_INVALID; + rn = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | ((m >> 3) & 7); + mn = ((~p0 & 0x20) >> 2) | ((p0 & 8) << 1) | (m & 7); + if (op == 0x93) + reg = rex2_register(rn, w == 8 ? 8 : 4); + else { + if (rn > 7) + return X86_FEATURE_INVALID; + reg = (x86_reg)(X86_REG_K0 + rn); + } + if (reg == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCInst_clear(in); + MCInst_setOpcode(in, X86_FEATURE_APX_KMOV_BASE + fi); + MCOperand_CreateImm0(in, op); + MCOperand_CreateImm0(in, reg); + MCOperand_CreateImm0(in, mem); + if (!mem) { + if (op == 0x92) + rm = rex2_register(mn, w == 8 ? 8 : 4); + else { + if (mn > 7) + return X86_FEATURE_INVALID; + rm = (x86_reg)(X86_REG_K0 + mn); + } + if (rm == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCOperand_CreateImm0(in, rm); + MCOperand_CreateImm0(in, w); + *size = (uint16_t)(off + 6); + set_apx_evex_encoding_detail(in, e, off, segp, a32, NULL); + return X86_FEATURE_DECODED; + } + if (!decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &mm)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + add_feature_memory_operands(in, &mm); + MCOperand_CreateImm0(in, seg); + MCOperand_CreateImm0(in, a32 ? 4 : 8); + MCOperand_CreateImm0(in, w); + *size = (uint16_t)mm.length; + set_apx_evex_encoding_detail(in, e, off, segp, a32, &mm); + return X86_FEATURE_DECODED; +} + +static x86_feature_decode_result decode_apx_movrs(csh handle, + const uint8_t *code, + size_t len, MCInst *in, + uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0; + uint8_t segp = 0, p0, p1, p2, op, m, w; + bool a32 = false, bad = false; + x86_reg dst, seg; + unsigned rn; + x86_feature_memory mm; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 4) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 6) + return X86_FEATURE_INVALID; + e = &code[off]; + op = e[4]; + if (op != 0x8a && op != 0x8b) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + if ((m & 0xc0) == 0xc0 || (p1 & 0x78) != 0x78 || p2 != 8) + return X86_FEATURE_INVALID; + if (op == 0x8a) { + if (p1 & 0x83) + return X86_FEATURE_INVALID; + w = 1; + } else { + if ((p1 & 3) > 1) + return X86_FEATURE_INVALID; + w = (p1 & 0x80) ? 8 : (p1 & 1) ? 2 : 4; + } + rn = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | ((m >> 3) & 7); + dst = rex2_register(rn, w); + if (dst == X86_REG_INVALID || + !decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &mm)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + MCInst_clear(in); + MCInst_setOpcode(in, X86_FEATURE_APX_MOVRS); + MCOperand_CreateImm0(in, dst); + add_feature_memory_operands(in, &mm); + MCOperand_CreateImm0(in, seg); + MCOperand_CreateImm0(in, a32 ? 4 : 8); + MCOperand_CreateImm0(in, w); + *size = (uint16_t)mm.length; + set_apx_evex_encoding_detail(in, e, off, segp, a32, &mm); + return X86_FEATURE_DECODED; } static x86_feature_decode_result decode_apx_invalidate(csh handle,const uint8_t*code,size_t len,MCInst*in,uint16_t*size) @@ -2597,74 +3343,503 @@ decode_apx_msr(csh handle, const uint8_t *code, size_t code_len, return X86_FEATURE_DECODED; } -static x86_feature_decode_result decode_apx_bls(csh handle,const uint8_t *code,size_t len,MCInst *instr,uint16_t *size) -{ - const cs_struct *arch=(const cs_struct *)(uintptr_t)handle;const uint8_t *e;size_t off=0;uint8_t segp=0,p0,p1,p2,m,w,g;bool a32=false,bad=false,mem,nf;x86_reg dst,src=X86_REG_INVALID,seg;unsigned dn,rn,feature;x86_feature_memory memory; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=2)return X86_FEATURE_NOT_HANDLED;if(len-off<5)return X86_FEATURE_INVALID;e=&code[off];if(e[4]!=0xf3)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||len-off<6||off+6>15)return X86_FEATURE_INVALID; - p0=e[1];p1=e[2];p2=e[3];m=e[5];g=(m>>3)&7;if(g<1||g>3)return X86_FEATURE_NOT_HANDLED;mem=(m&0xc0)!=0xc0;nf=(p2&4)!=0;if((p1&3)!=0||(p2&0xf3)!=0||(!mem&&!(p1&4)))return X86_FEATURE_INVALID; - w=(p1&0x80)?8:4;dn=((~p2&8)<<1)|((~p1&0x78)>>3);dst=rex2_register(dn,w);if(dst==X86_REG_INVALID)return X86_FEATURE_INVALID;feature=g==1?X86_FEATURE_APX_BLSR:g==2?X86_FEATURE_APX_BLSMSK:X86_FEATURE_APX_BLSI; - MCInst_clear(instr);MCInst_setOpcode(instr,feature);MCOperand_CreateImm0(instr,dst);MCOperand_CreateImm0(instr,mem); - if(!mem){rn=((~p0&0x20)>>2)|((p0&8)<<1)|(m&7);src=rex2_register(rn,w);if(src==X86_REG_INVALID)return X86_FEATURE_INVALID;MCOperand_CreateImm0(instr,src);MCOperand_CreateImm0(instr,w);MCOperand_CreateImm0(instr,1);MCOperand_CreateImm0(instr,nf);*size=(uint16_t)(off+6);set_apx_evex_encoding_detail(instr,e,off,segp,a32,NULL);return X86_FEATURE_DECODED;} - if(!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&memory))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);add_feature_memory_operands(instr,&memory);MCOperand_CreateImm0(instr,seg);MCOperand_CreateImm0(instr,a32?4:8);MCOperand_CreateImm0(instr,w);MCOperand_CreateImm0(instr,1);MCOperand_CreateImm0(instr,nf);*size=(uint16_t)memory.length;set_apx_evex_encoding_detail(instr,e,off,segp,a32,&memory);return X86_FEATURE_DECODED; -} - -static x86_feature_decode_result decode_apx_bextr(csh handle,const uint8_t *code,size_t len,MCInst *instr,uint16_t *size) -{ - const cs_struct *arch=(const cs_struct *)(uintptr_t)handle;const uint8_t *e;size_t off=0;uint8_t segp=0,p0,p1,p2,m,w;bool a32=false,bad=false,mem,nf;x86_reg dst,ctl,data=X86_REG_INVALID,seg;unsigned dn,cn,rn;x86_feature_memory memory; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=2)return X86_FEATURE_NOT_HANDLED;if(len-off<5)return X86_FEATURE_INVALID;e=&code[off];if(e[4]!=0xf7)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||len-off<6||off+6>15)return X86_FEATURE_INVALID; - p0=e[1];p1=e[2];p2=e[3];m=e[5];mem=(m&0xc0)!=0xc0;nf=(p2&4)!=0;if((p2&0xf3)!=0||(!mem&&!(p1&4)))return X86_FEATURE_INVALID;unsigned feature=(p1&3)==0?X86_FEATURE_APX_BEXTR:(p1&3)==2?X86_FEATURE_APX_SARX:(p1&3)==1?X86_FEATURE_APX_SHLX:X86_FEATURE_APX_SHRX;if(feature!=X86_FEATURE_APX_BEXTR&&nf)return X86_FEATURE_INVALID;w=(p1&0x80)?8:4;dn=((~p0&0x80)>>4)|(~p0&0x10)|((m>>3)&7);cn=((~p2&8)<<1)|((~p1&0x78)>>3);dst=rex2_register(dn,w);ctl=rex2_register(cn,w);if(dst==X86_REG_INVALID||ctl==X86_REG_INVALID)return X86_FEATURE_INVALID; - MCInst_clear(instr);MCInst_setOpcode(instr,feature);MCOperand_CreateImm0(instr,dst);MCOperand_CreateImm0(instr,ctl);MCOperand_CreateImm0(instr,mem); - if(!mem){rn=((~p0&0x20)>>2)|((p0&8)<<1)|(m&7);data=rex2_register(rn,w);if(data==X86_REG_INVALID)return X86_FEATURE_INVALID;MCOperand_CreateImm0(instr,data);MCOperand_CreateImm0(instr,w);MCOperand_CreateImm0(instr,nf);*size=(uint16_t)(off+6);set_apx_evex_encoding_detail(instr,e,off,segp,a32,NULL);return X86_FEATURE_DECODED;} - if(!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&memory))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);add_feature_memory_operands(instr,&memory);MCOperand_CreateImm0(instr,seg);MCOperand_CreateImm0(instr,a32?4:8);MCOperand_CreateImm0(instr,w);MCOperand_CreateImm0(instr,nf);*size=(uint16_t)memory.length;set_apx_evex_encoding_detail(instr,e,off,segp,a32,&memory);return X86_FEATURE_DECODED; -} - -static x86_feature_decode_result decode_apx_count(csh handle,const uint8_t *code,size_t len,MCInst *instr,uint16_t *size) -{ - const cs_struct *arch=(const cs_struct *)(uintptr_t)handle;const uint8_t *e;size_t off=0;uint8_t segp=0,p0,p1,p2,op,m,w,pp;bool a32=false,bad=false,mem,nf;x86_reg dst,src=X86_REG_INVALID,seg;unsigned dn,rn,feature;x86_feature_memory memory; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=4)return X86_FEATURE_NOT_HANDLED;if(len-off<5)return X86_FEATURE_INVALID;e=&code[off];op=e[4];if(op!=0xf5&&op!=0xf4&&op!=0x88)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||len-off<6||off+6>15)return X86_FEATURE_INVALID; - p0=e[1];p1=e[2];p2=e[3];m=e[5];pp=p1&3;mem=(m&0xc0)!=0xc0;nf=(p2&4)!=0;if(pp>1||(p1&0x78)!=0x78||!(p2&8)||(p2&0xf3)!=0||(!mem&&!(p1&4)))return X86_FEATURE_INVALID;w=(p1&0x80)?8:pp?2:4;feature=op==0xf5?X86_FEATURE_APX_LZCNT:op==0xf4?X86_FEATURE_APX_TZCNT:X86_FEATURE_APX_POPCNT;dn=((~p0&0x80)>>4)|(~p0&0x10)|((m>>3)&7);dst=rex2_register(dn,w);if(dst==X86_REG_INVALID)return X86_FEATURE_INVALID; - MCInst_clear(instr);MCInst_setOpcode(instr,feature);MCOperand_CreateImm0(instr,dst);MCOperand_CreateImm0(instr,mem); - if(!mem){rn=((~p0&0x20)>>2)|((p0&8)<<1)|(m&7);src=rex2_register(rn,w);if(src==X86_REG_INVALID)return X86_FEATURE_INVALID;MCOperand_CreateImm0(instr,src);MCOperand_CreateImm0(instr,w);MCOperand_CreateImm0(instr,1);MCOperand_CreateImm0(instr,nf);*size=(uint16_t)(off+6);set_apx_evex_encoding_detail(instr,e,off,segp,a32,NULL);return X86_FEATURE_DECODED;} - if(!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&memory))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);add_feature_memory_operands(instr,&memory);MCOperand_CreateImm0(instr,seg);MCOperand_CreateImm0(instr,a32?4:8);MCOperand_CreateImm0(instr,w);MCOperand_CreateImm0(instr,1);MCOperand_CreateImm0(instr,nf);*size=(uint16_t)memory.length;set_apx_evex_encoding_detail(instr,e,off,segp,a32,&memory);return X86_FEATURE_DECODED; -} - -static x86_feature_decode_result decode_apx_rorx(csh handle,const uint8_t *code,size_t len,MCInst *instr,uint16_t *size) -{ - const cs_struct *arch=(const cs_struct *)(uintptr_t)handle;const uint8_t *e;size_t off=0,io;uint8_t segp=0,p0,p1,p2,m,w,imm;bool a32=false,bad=false,mem;x86_reg dst,src=X86_REG_INVALID,seg;unsigned dn,rn;x86_feature_memory memory; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=3)return X86_FEATURE_NOT_HANDLED;if(len-off<5)return X86_FEATURE_INVALID;e=&code[off];if(e[4]!=0xf0)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||len-off<7||off+7>15)return X86_FEATURE_INVALID; - p0=e[1];p1=e[2];p2=e[3];m=e[5];mem=(m&0xc0)!=0xc0;if((p1&0x7b)!=0x7b||(!mem&&!(p1&4))||p2!=8)return X86_FEATURE_INVALID;w=(p1&0x80)?8:4;dn=((~p0&0x80)>>4)|(~p0&0x10)|((m>>3)&7);dst=rex2_register(dn,w);if(dst==X86_REG_INVALID)return X86_FEATURE_INVALID; - MCInst_clear(instr);MCInst_setOpcode(instr,X86_FEATURE_APX_RORX);MCOperand_CreateImm0(instr,dst);MCOperand_CreateImm0(instr,mem); - if(!mem){rn=((~p0&0x20)>>2)|((p0&8)<<1)|(m&7);src=rex2_register(rn,w);if(src==X86_REG_INVALID)return X86_FEATURE_INVALID;io=off+6;}else{if(!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&memory))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);add_feature_memory_operands(instr,&memory);MCOperand_CreateImm0(instr,seg);MCOperand_CreateImm0(instr,a32?4:8);io=memory.length;} - if(io>=len||io>=15)return X86_FEATURE_INVALID;imm=code[io];if(!mem)MCOperand_CreateImm0(instr,src);MCOperand_CreateImm0(instr,w);MCOperand_CreateImm0(instr,imm);*size=(uint16_t)(io+1);set_apx_evex_encoding_detail(instr,e,off,segp,a32,mem?&memory:NULL);instr->imm_size=1;if(instr->flat_insn->detail){instr->flat_insn->detail->x86.encoding.imm_offset=(uint8_t)io;instr->flat_insn->detail->x86.encoding.imm_size=1;}return X86_FEATURE_DECODED; -} - -static x86_feature_decode_result decode_apx_mulx(csh handle,const uint8_t *code,size_t len,MCInst *instr,uint16_t *size) -{ - const cs_struct *arch=(const cs_struct *)(uintptr_t)handle;const uint8_t *e;size_t off=0;uint8_t segp=0,p0,p1,p2,m,w;bool a32=false,bad=false,mem;x86_reg d1,d2,src=X86_REG_INVALID,seg;unsigned n1,n2,rn;x86_feature_memory memory; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=2)return X86_FEATURE_NOT_HANDLED;if(len-off<5)return X86_FEATURE_INVALID;e=&code[off];if(e[4]!=0xf6)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||len-off<6||off+6>15)return X86_FEATURE_INVALID; - p0=e[1];p1=e[2];p2=e[3];m=e[5];mem=(m&0xc0)!=0xc0;if((p1&3)!=3||(!mem&&!(p1&4))||(p2&0xf7)!=0)return X86_FEATURE_INVALID;w=(p1&0x80)?8:4;n1=((~p0&0x80)>>4)|(~p0&0x10)|((m>>3)&7);n2=((~p2&8)<<1)|((~p1&0x78)>>3);d1=rex2_register(n1,w);d2=rex2_register(n2,w);if(d1==X86_REG_INVALID||d2==X86_REG_INVALID)return X86_FEATURE_INVALID; - MCInst_clear(instr);MCInst_setOpcode(instr,X86_FEATURE_APX_MULX);MCOperand_CreateImm0(instr,d1);MCOperand_CreateImm0(instr,d2);MCOperand_CreateImm0(instr,mem); - if(!mem){rn=((~p0&0x20)>>2)|((p0&8)<<1)|(m&7);src=rex2_register(rn,w);if(src==X86_REG_INVALID)return X86_FEATURE_INVALID;MCOperand_CreateImm0(instr,src);MCOperand_CreateImm0(instr,w);*size=(uint16_t)(off+6);set_apx_evex_encoding_detail(instr,e,off,segp,a32,NULL);return X86_FEATURE_DECODED;} - if(!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&memory))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);add_feature_memory_operands(instr,&memory);MCOperand_CreateImm0(instr,seg);MCOperand_CreateImm0(instr,a32?4:8);MCOperand_CreateImm0(instr,w);*size=(uint16_t)memory.length;set_apx_evex_encoding_detail(instr,e,off,segp,a32,&memory);return X86_FEATURE_DECODED; -} - -static x86_feature_decode_result decode_apx_convert(csh handle,const uint8_t *code,size_t len,MCInst *instr,uint16_t *size) -{ - const cs_struct *arch=(const cs_struct *)(uintptr_t)handle;const uint8_t *e;size_t off=0;uint8_t segp=0,p0,p1,p2,op,m,pp,dw,sw;bool a32=false,bad=false,mem,crc,store;x86_reg d,s=X86_REG_INVALID,seg;unsigned dn,rn;x86_feature_memory mm; - while(off0x4f)return X86_FEATURE_NOT_HANDLED;++off;} - if(off==len||len-off<2||(code[off+1]&7)!=4)return X86_FEATURE_NOT_HANDLED;if(len-off<5)return X86_FEATURE_INVALID;e=&code[off];op=e[4];if(op!=0x60&&op!=0x61&&op!=0xf0&&op!=0xf1)return X86_FEATURE_NOT_HANDLED;if(!(arch->mode&CS_MODE_64)||bad||len-off<6||off+6>15)return X86_FEATURE_INVALID; - p0=e[1];p1=e[2];p2=e[3];m=e[5];pp=p1&3;mem=(m&0xc0)!=0xc0;crc=op>=0xf0;store=op==0x61;if(pp>1||(p1&0x78)!=0x78||p2!=8||(!mem&&!(p1&4)))return X86_FEATURE_INVALID; - /* As in the other promoted forms, W selects 64-bit operands over 66. */ - if(crc){if(op==0xf0&&pp)return X86_FEATURE_INVALID;dw=(p1&0x80)?8:4;sw=op==0xf0?1:(p1&0x80)?8:(pp?2:4);store=false;}else{dw=sw=(p1&0x80)?8:(pp?2:4);} - dn=((~p0&0x80)>>4)|(~p0&0x10)|((m>>3)&7);d=rex2_register(dn,store?sw:dw);if(d==X86_REG_INVALID)return X86_FEATURE_INVALID; - MCInst_clear(instr);MCInst_setOpcode(instr,crc?X86_FEATURE_APX_CRC32:X86_FEATURE_APX_MOVBE);MCOperand_CreateImm0(instr,d);MCOperand_CreateImm0(instr,mem);MCOperand_CreateImm0(instr,store); - if(!mem){rn=((~p0&0x20)>>2)|((p0&8)<<1)|(m&7);s=rex2_register(rn,store?dw:sw);if(s==X86_REG_INVALID)return X86_FEATURE_INVALID;MCOperand_CreateImm0(instr,s);MCOperand_CreateImm0(instr,dw);MCOperand_CreateImm0(instr,sw);*size=(uint16_t)(off+6);set_apx_evex_encoding_detail(instr,e,off,segp,a32,NULL);return X86_FEATURE_DECODED;} - if(!decode_apx_evex_memory(code,len,off+5,p0,p1,a32,&mm))return X86_FEATURE_INVALID;seg=apx_segment_register(segp);add_feature_memory_operands(instr,&mm);MCOperand_CreateImm0(instr,seg);MCOperand_CreateImm0(instr,a32?4:8);MCOperand_CreateImm0(instr,dw);MCOperand_CreateImm0(instr,sw);*size=(uint16_t)mm.length;set_apx_evex_encoding_detail(instr,e,off,segp,a32,&mm);return X86_FEATURE_DECODED; +static x86_feature_decode_result decode_apx_bls(csh handle, const uint8_t *code, + size_t len, MCInst *instr, + uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0; + uint8_t segp = 0, p0, p1, p2, m, w, g; + bool a32 = false, bad = false, mem, nf; + x86_reg dst, src = X86_REG_INVALID, seg; + unsigned dn, rn, feature; + x86_feature_memory memory; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 2) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 5) + return X86_FEATURE_INVALID; + e = &code[off]; + if (e[4] != 0xf3) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || len - off < 6 || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + g = (m >> 3) & 7; + if (g < 1 || g > 3) + return X86_FEATURE_NOT_HANDLED; + mem = (m & 0xc0) != 0xc0; + nf = (p2 & 4) != 0; + if ((p1 & 3) != 0 || (p2 & 0xf3) != 0 || (!mem && !(p1 & 4))) + return X86_FEATURE_INVALID; + w = (p1 & 0x80) ? 8 : 4; + dn = ((~p2 & 8) << 1) | ((~p1 & 0x78) >> 3); + dst = rex2_register(dn, w); + if (dst == X86_REG_INVALID) + return X86_FEATURE_INVALID; + feature = g == 1 ? X86_FEATURE_APX_BLSR + : g == 2 ? X86_FEATURE_APX_BLSMSK + : X86_FEATURE_APX_BLSI; + MCInst_clear(instr); + MCInst_setOpcode(instr, feature); + MCOperand_CreateImm0(instr, dst); + MCOperand_CreateImm0(instr, mem); + if (!mem) { + rn = ((~p0 & 0x20) >> 2) | ((p0 & 8) << 1) | (m & 7); + src = rex2_register(rn, w); + if (src == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCOperand_CreateImm0(instr, src); + MCOperand_CreateImm0(instr, w); + MCOperand_CreateImm0(instr, 1); + MCOperand_CreateImm0(instr, nf); + *size = (uint16_t)(off + 6); + set_apx_evex_encoding_detail(instr, e, off, segp, a32, NULL); + return X86_FEATURE_DECODED; + } + if (!decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &memory)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + add_feature_memory_operands(instr, &memory); + MCOperand_CreateImm0(instr, seg); + MCOperand_CreateImm0(instr, a32 ? 4 : 8); + MCOperand_CreateImm0(instr, w); + MCOperand_CreateImm0(instr, 1); + MCOperand_CreateImm0(instr, nf); + *size = (uint16_t)memory.length; + set_apx_evex_encoding_detail(instr, e, off, segp, a32, &memory); + return X86_FEATURE_DECODED; +} + +static x86_feature_decode_result decode_apx_bextr(csh handle, + const uint8_t *code, + size_t len, MCInst *instr, + uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0; + uint8_t segp = 0, p0, p1, p2, m, w; + bool a32 = false, bad = false, mem, nf; + x86_reg dst, ctl, data = X86_REG_INVALID, seg; + unsigned dn, cn, rn; + x86_feature_memory memory; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 2) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 5) + return X86_FEATURE_INVALID; + e = &code[off]; + if (e[4] != 0xf7) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || len - off < 6 || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + mem = (m & 0xc0) != 0xc0; + nf = (p2 & 4) != 0; + if ((p2 & 0xf3) != 0 || (!mem && !(p1 & 4))) + return X86_FEATURE_INVALID; + unsigned feature = (p1 & 3) == 0 ? X86_FEATURE_APX_BEXTR + : (p1 & 3) == 2 ? X86_FEATURE_APX_SARX + : (p1 & 3) == 1 ? X86_FEATURE_APX_SHLX + : X86_FEATURE_APX_SHRX; + if (feature != X86_FEATURE_APX_BEXTR && nf) + return X86_FEATURE_INVALID; + w = (p1 & 0x80) ? 8 : 4; + dn = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | ((m >> 3) & 7); + cn = ((~p2 & 8) << 1) | ((~p1 & 0x78) >> 3); + dst = rex2_register(dn, w); + ctl = rex2_register(cn, w); + if (dst == X86_REG_INVALID || ctl == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCInst_clear(instr); + MCInst_setOpcode(instr, feature); + MCOperand_CreateImm0(instr, dst); + MCOperand_CreateImm0(instr, ctl); + MCOperand_CreateImm0(instr, mem); + if (!mem) { + rn = ((~p0 & 0x20) >> 2) | ((p0 & 8) << 1) | (m & 7); + data = rex2_register(rn, w); + if (data == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCOperand_CreateImm0(instr, data); + MCOperand_CreateImm0(instr, w); + MCOperand_CreateImm0(instr, nf); + *size = (uint16_t)(off + 6); + set_apx_evex_encoding_detail(instr, e, off, segp, a32, NULL); + return X86_FEATURE_DECODED; + } + if (!decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &memory)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + add_feature_memory_operands(instr, &memory); + MCOperand_CreateImm0(instr, seg); + MCOperand_CreateImm0(instr, a32 ? 4 : 8); + MCOperand_CreateImm0(instr, w); + MCOperand_CreateImm0(instr, nf); + *size = (uint16_t)memory.length; + set_apx_evex_encoding_detail(instr, e, off, segp, a32, &memory); + return X86_FEATURE_DECODED; +} + +static x86_feature_decode_result decode_apx_count(csh handle, + const uint8_t *code, + size_t len, MCInst *instr, + uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0; + uint8_t segp = 0, p0, p1, p2, op, m, w, pp; + bool a32 = false, bad = false, mem, nf; + x86_reg dst, src = X86_REG_INVALID, seg; + unsigned dn, rn, feature; + x86_feature_memory memory; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 4) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 5) + return X86_FEATURE_INVALID; + e = &code[off]; + op = e[4]; + if (op != 0xf5 && op != 0xf4 && op != 0x88) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || len - off < 6 || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + pp = p1 & 3; + mem = (m & 0xc0) != 0xc0; + nf = (p2 & 4) != 0; + if (pp > 1 || (p1 & 0x78) != 0x78 || !(p2 & 8) || (p2 & 0xf3) != 0 || + (!mem && !(p1 & 4))) + return X86_FEATURE_INVALID; + w = (p1 & 0x80) ? 8 : pp ? 2 : 4; + feature = op == 0xf5 ? X86_FEATURE_APX_LZCNT + : op == 0xf4 ? X86_FEATURE_APX_TZCNT + : X86_FEATURE_APX_POPCNT; + dn = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | ((m >> 3) & 7); + dst = rex2_register(dn, w); + if (dst == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCInst_clear(instr); + MCInst_setOpcode(instr, feature); + MCOperand_CreateImm0(instr, dst); + MCOperand_CreateImm0(instr, mem); + if (!mem) { + rn = ((~p0 & 0x20) >> 2) | ((p0 & 8) << 1) | (m & 7); + src = rex2_register(rn, w); + if (src == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCOperand_CreateImm0(instr, src); + MCOperand_CreateImm0(instr, w); + MCOperand_CreateImm0(instr, 1); + MCOperand_CreateImm0(instr, nf); + *size = (uint16_t)(off + 6); + set_apx_evex_encoding_detail(instr, e, off, segp, a32, NULL); + return X86_FEATURE_DECODED; + } + if (!decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &memory)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + add_feature_memory_operands(instr, &memory); + MCOperand_CreateImm0(instr, seg); + MCOperand_CreateImm0(instr, a32 ? 4 : 8); + MCOperand_CreateImm0(instr, w); + MCOperand_CreateImm0(instr, 1); + MCOperand_CreateImm0(instr, nf); + *size = (uint16_t)memory.length; + set_apx_evex_encoding_detail(instr, e, off, segp, a32, &memory); + return X86_FEATURE_DECODED; +} + +static x86_feature_decode_result decode_apx_rorx(csh handle, + const uint8_t *code, + size_t len, MCInst *instr, + uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0, io; + uint8_t segp = 0, p0, p1, p2, m, w, imm; + bool a32 = false, bad = false, mem; + x86_reg dst, src = X86_REG_INVALID, seg; + unsigned dn, rn; + x86_feature_memory memory; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 3) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 5) + return X86_FEATURE_INVALID; + e = &code[off]; + if (e[4] != 0xf0) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || len - off < 7 || off + 7 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + mem = (m & 0xc0) != 0xc0; + if ((p1 & 0x7b) != 0x7b || (!mem && !(p1 & 4)) || p2 != 8) + return X86_FEATURE_INVALID; + w = (p1 & 0x80) ? 8 : 4; + dn = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | ((m >> 3) & 7); + dst = rex2_register(dn, w); + if (dst == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCInst_clear(instr); + MCInst_setOpcode(instr, X86_FEATURE_APX_RORX); + MCOperand_CreateImm0(instr, dst); + MCOperand_CreateImm0(instr, mem); + if (!mem) { + rn = ((~p0 & 0x20) >> 2) | ((p0 & 8) << 1) | (m & 7); + src = rex2_register(rn, w); + if (src == X86_REG_INVALID) + return X86_FEATURE_INVALID; + io = off + 6; + } else { + if (!decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &memory)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + add_feature_memory_operands(instr, &memory); + MCOperand_CreateImm0(instr, seg); + MCOperand_CreateImm0(instr, a32 ? 4 : 8); + io = memory.length; + } + if (io >= len || io >= 15) + return X86_FEATURE_INVALID; + imm = code[io]; + if (!mem) + MCOperand_CreateImm0(instr, src); + MCOperand_CreateImm0(instr, w); + MCOperand_CreateImm0(instr, imm); + *size = (uint16_t)(io + 1); + set_apx_evex_encoding_detail(instr, e, off, segp, a32, mem ? &memory : NULL); + instr->imm_size = 1; + if (instr->flat_insn->detail) { + instr->flat_insn->detail->x86.encoding.imm_offset = (uint8_t)io; + instr->flat_insn->detail->x86.encoding.imm_size = 1; + } + return X86_FEATURE_DECODED; +} + +static x86_feature_decode_result decode_apx_mulx(csh handle, + const uint8_t *code, + size_t len, MCInst *instr, + uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0; + uint8_t segp = 0, p0, p1, p2, m, w; + bool a32 = false, bad = false, mem; + x86_reg d1, d2, src = X86_REG_INVALID, seg; + unsigned n1, n2, rn; + x86_feature_memory memory; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 2) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 5) + return X86_FEATURE_INVALID; + e = &code[off]; + if (e[4] != 0xf6) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || len - off < 6 || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + mem = (m & 0xc0) != 0xc0; + if ((p1 & 3) != 3 || (!mem && !(p1 & 4)) || (p2 & 0xf7) != 0) + return X86_FEATURE_INVALID; + w = (p1 & 0x80) ? 8 : 4; + n1 = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | ((m >> 3) & 7); + n2 = ((~p2 & 8) << 1) | ((~p1 & 0x78) >> 3); + d1 = rex2_register(n1, w); + d2 = rex2_register(n2, w); + if (d1 == X86_REG_INVALID || d2 == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCInst_clear(instr); + MCInst_setOpcode(instr, X86_FEATURE_APX_MULX); + MCOperand_CreateImm0(instr, d1); + MCOperand_CreateImm0(instr, d2); + MCOperand_CreateImm0(instr, mem); + if (!mem) { + rn = ((~p0 & 0x20) >> 2) | ((p0 & 8) << 1) | (m & 7); + src = rex2_register(rn, w); + if (src == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCOperand_CreateImm0(instr, src); + MCOperand_CreateImm0(instr, w); + *size = (uint16_t)(off + 6); + set_apx_evex_encoding_detail(instr, e, off, segp, a32, NULL); + return X86_FEATURE_DECODED; + } + if (!decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &memory)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + add_feature_memory_operands(instr, &memory); + MCOperand_CreateImm0(instr, seg); + MCOperand_CreateImm0(instr, a32 ? 4 : 8); + MCOperand_CreateImm0(instr, w); + *size = (uint16_t)memory.length; + set_apx_evex_encoding_detail(instr, e, off, segp, a32, &memory); + return X86_FEATURE_DECODED; +} + +static x86_feature_decode_result decode_apx_convert(csh handle, + const uint8_t *code, + size_t len, MCInst *instr, + uint16_t *size) { + const cs_struct *arch = (const cs_struct *)(uintptr_t)handle; + const uint8_t *e; + size_t off = 0; + uint8_t segp = 0, p0, p1, p2, op, m, pp, dw, sw; + bool a32 = false, bad = false, mem, crc, store; + x86_reg d, s = X86_REG_INVALID, seg; + unsigned dn, rn; + x86_feature_memory mm; + while (off < len && code[off] != 0x62) { + uint8_t p = code[off]; + if (is_apx_evex_segment_prefix(p)) + segp = p; + else if (p == 0x67) + a32 = true; + else if (p == 0x66 || p == 0xf0 || p == 0xf2 || p == 0xf3 || + is_effective_rex(code, len, off)) + bad = true; + else if (p < 0x40 || p > 0x4f) + return X86_FEATURE_NOT_HANDLED; + ++off; + } + if (off == len || len - off < 2 || (code[off + 1] & 7) != 4) + return X86_FEATURE_NOT_HANDLED; + if (len - off < 5) + return X86_FEATURE_INVALID; + e = &code[off]; + op = e[4]; + if (op != 0x60 && op != 0x61 && op != 0xf0 && op != 0xf1) + return X86_FEATURE_NOT_HANDLED; + if (!(arch->mode & CS_MODE_64) || bad || len - off < 6 || off + 6 > 15) + return X86_FEATURE_INVALID; + p0 = e[1]; + p1 = e[2]; + p2 = e[3]; + m = e[5]; + pp = p1 & 3; + mem = (m & 0xc0) != 0xc0; + crc = op >= 0xf0; + store = op == 0x61; + if (pp > 1 || (p1 & 0x78) != 0x78 || p2 != 8 || (!mem && !(p1 & 4))) + return X86_FEATURE_INVALID; + /* As in the other promoted forms, W selects 64-bit operands over 66. */ + if (crc) { + if (op == 0xf0 && pp) + return X86_FEATURE_INVALID; + dw = (p1 & 0x80) ? 8 : 4; + sw = op == 0xf0 ? 1 : (p1 & 0x80) ? 8 : (pp ? 2 : 4); + store = false; + } else { + dw = sw = (p1 & 0x80) ? 8 : (pp ? 2 : 4); + } + dn = ((~p0 & 0x80) >> 4) | (~p0 & 0x10) | ((m >> 3) & 7); + d = rex2_register(dn, store ? sw : dw); + if (d == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCInst_clear(instr); + MCInst_setOpcode(instr, crc ? X86_FEATURE_APX_CRC32 : X86_FEATURE_APX_MOVBE); + MCOperand_CreateImm0(instr, d); + MCOperand_CreateImm0(instr, mem); + MCOperand_CreateImm0(instr, store); + if (!mem) { + rn = ((~p0 & 0x20) >> 2) | ((p0 & 8) << 1) | (m & 7); + s = rex2_register(rn, store ? dw : sw); + if (s == X86_REG_INVALID) + return X86_FEATURE_INVALID; + MCOperand_CreateImm0(instr, s); + MCOperand_CreateImm0(instr, dw); + MCOperand_CreateImm0(instr, sw); + *size = (uint16_t)(off + 6); + set_apx_evex_encoding_detail(instr, e, off, segp, a32, NULL); + return X86_FEATURE_DECODED; + } + if (!decode_apx_evex_memory(code, len, off + 5, p0, p1, a32, &mm)) + return X86_FEATURE_INVALID; + seg = apx_segment_register(segp); + add_feature_memory_operands(instr, &mm); + MCOperand_CreateImm0(instr, seg); + MCOperand_CreateImm0(instr, a32 ? 4 : 8); + MCOperand_CreateImm0(instr, dw); + MCOperand_CreateImm0(instr, sw); + *size = (uint16_t)mm.length; + set_apx_evex_encoding_detail(instr, e, off, segp, a32, &mm); + return X86_FEATURE_DECODED; } static x86_feature_decode_result @@ -4944,10 +6119,131 @@ static bool print_apx_cmpccxadd(MCInst*in,SStream*s,bool att) static const char*const names[]={"cmpoxadd","cmpnoxadd","cmpbxadd","cmpnbxadd","cmpzxadd","cmpnzxadd","cmpbexadd","cmpnbexadd","cmpsxadd","cmpnsxadd","cmppxadd","cmpnpxadd","cmplxadd","cmpnlxadd","cmplexadd","cmpnlexadd"};unsigned op=MCInst_getOpcode(in),idx,i;x86_reg cmp,add,seg;x86_feature_memory m;uint8_t w;cs_detail*d;cs_x86*x;if(op=X86_FEATURE_APX_CMPCCXADD_BASE+16)return false;idx=op-X86_FEATURE_APX_CMPCCXADD_BASE;if(MCInst_getNumOperands(in)!=9||!get_feature_memory(in,2,&m))return false;cmp=(x86_reg)MCOperand_getImm(MCInst_getOperand(in,0));add=(x86_reg)MCOperand_getImm(MCInst_getOperand(in,1));seg=(x86_reg)MCOperand_getImm(MCInst_getOperand(in,6));w=(uint8_t)MCOperand_getImm(MCInst_getOperand(in,8));SStream_concat(s,att?"%s%c\t":"%s\t",names[idx],w==4?'l':'q');for(i=0;i<3;i++){unsigned k=att?2-i:i;if(i)SStream_concat0(s,", ");if(k==0){if(!att)SStream_concat0(s,w==4?"dword ptr ":"qword ptr ");if(seg!=X86_REG_INVALID)SStream_concat(s,att?"%%%s:":"%s:",feature_register_name(seg));if(!print_feature_memory(s,&m,att))return false;}else SStream_concat(s,att?"%%%s":"%s",X86_reg_name((csh)in->csh,k==1?cmp:add));}if(!in->flat_insn->detail)return true;d=in->flat_insn->detail;x=&d->x86;for(i=0;i<3;i++){unsigned k=att?2-i:i;cs_x86_op*o=&x->operands[i];if(k==0){set_feature_memory_operand(o,&m,w,CS_AC_READ_WRITE);o->mem.segment=seg;}else{o->type=X86_OP_REG;o->reg=k==1?cmp:add;o->size=w;o->access=k==1?CS_AC_READ_WRITE:CS_AC_READ;}}x->op_count=3;d->regs_write[d->regs_write_count++]=X86_REG_EFLAGS;x->eflags=X86_EFLAGS_MODIFY_OF|X86_EFLAGS_MODIFY_SF|X86_EFLAGS_MODIFY_ZF|X86_EFLAGS_MODIFY_AF|X86_EFLAGS_MODIFY_PF|X86_EFLAGS_MODIFY_CF;return true; } -static bool print_apx_ccmp(MCInst*in,SStream*s,bool att) -{ -static const char*const ccmp_names[]={"ccmpo","ccmpno","ccmpb","ccmpnb","ccmpz","ccmpnz","ccmpbe","ccmpnbe","ccmps","ccmpns","ccmpt","ccmpf","ccmpl","ccmpnl","ccmple","ccmpnle"};static const char*const ctest_names[]={"ctesto","ctestno","ctestb","ctestnb","ctestz","ctestnz","ctestbe","ctestnbe","ctests","ctestns","ctestt","ctestf","ctestl","ctestnl","ctestle","ctestnle"};static const char*const dfvs[]={"","cf","zf","zf,cf","sf","sf,cf","sf,zf","sf,zf,cf","of","of,cf","of,zf","of,zf,cf","of,sf","of,sf,cf","of,sf,zf","of,sf,zf,cf"};unsigned op=MCInst_getOpcode(in),i,n,idx;bool mem,rmfirst,imm,ctest;x86_reg rr,rm=X86_REG_INVALID,seg=X86_REG_INVALID;x86_feature_memory m;uint8_t w,dfv;int64_t iv;cs_detail*d;cs_x86*x;ctest=op>=X86_FEATURE_APX_CTEST_BASE&&op=X86_FEATURE_APX_CCMP_BASE+16))return false;idx=op-(ctest?X86_FEATURE_APX_CTEST_BASE:X86_FEATURE_APX_CCMP_BASE);mem=MCOperand_getImm(MCInst_getOperand(in,0))!=0;rmfirst=MCOperand_getImm(MCInst_getOperand(in,1))!=0;rr=(x86_reg)MCOperand_getImm(MCInst_getOperand(in,2));memset(&m,0,sizeof(m));if(mem){if(MCInst_getNumOperands(in)!=13||!get_feature_memory(in,3,&m))return false;seg=(x86_reg)MCOperand_getImm(MCInst_getOperand(in,7));imm=MCOperand_getImm(MCInst_getOperand(in,9))!=0;iv=MCOperand_getImm(MCInst_getOperand(in,10));w=(uint8_t)MCOperand_getImm(MCInst_getOperand(in,11));dfv=(uint8_t)MCOperand_getImm(MCInst_getOperand(in,12));}else{if(MCInst_getNumOperands(in)!=8)return false;rm=(x86_reg)MCOperand_getImm(MCInst_getOperand(in,3));imm=MCOperand_getImm(MCInst_getOperand(in,4))!=0;iv=MCOperand_getImm(MCInst_getOperand(in,5));w=(uint8_t)MCOperand_getImm(MCInst_getOperand(in,6));dfv=(uint8_t)MCOperand_getImm(MCInst_getOperand(in,7));}if(w!=1&&w!=2&&w!=4&&w!=8)return false;if(att)SStream_concat(s,"%s%c\t{dfv=%s} ",(ctest?ctest_names:ccmp_names)[idx],w==1?'b':w==2?'w':w==4?'l':'q',dfvs[dfv]);else SStream_concat(s,"%s\t{dfv=%s} ",(ctest?ctest_names:ccmp_names)[idx],dfvs[dfv]);n=2;for(i=0;icsh,rr));}else if(mem){if(!att)SStream_concat0(s,w==1?"byte ptr ":w==2?"word ptr ":w==4?"dword ptr ":"qword ptr ");if(seg!=X86_REG_INVALID)SStream_concat(s,att?"%%%s:":"%s:",feature_register_name(seg));if(!print_feature_memory(s,&m,att))return false;}else SStream_concat(s,att?"%%%s":"%s",X86_reg_name((csh)in->csh,rm));} - if(!in->flat_insn->detail)return true;d=in->flat_insn->detail;x=&d->x86;for(i=0;ioperands[i];if(!isrm){if(imm){o->type=X86_OP_IMM;o->imm=iv;o->size=w;o->access=CS_AC_READ;}else{o->type=X86_OP_REG;o->reg=rr;o->size=w;o->access=CS_AC_READ;}}else if(mem){set_feature_memory_operand(o,&m,w,CS_AC_READ);o->mem.segment=seg;}else{o->type=X86_OP_REG;o->reg=rm;o->size=w;o->access=CS_AC_READ;}}x->op_count=2;d->regs_read[d->regs_read_count++]=X86_REG_EFLAGS;d->regs_write[d->regs_write_count++]=X86_REG_EFLAGS;x->eflags=ctest?(X86_EFLAGS_RESET_OF|X86_EFLAGS_MODIFY_SF|X86_EFLAGS_MODIFY_ZF|X86_EFLAGS_UNDEFINED_AF|X86_EFLAGS_MODIFY_PF|X86_EFLAGS_RESET_CF):(X86_EFLAGS_MODIFY_OF|X86_EFLAGS_MODIFY_SF|X86_EFLAGS_MODIFY_ZF|X86_EFLAGS_MODIFY_AF|X86_EFLAGS_MODIFY_PF|X86_EFLAGS_MODIFY_CF);return true; +static bool print_apx_ccmp(MCInst *in, SStream *s, bool att) { + static const char *const ccmp_names[] = { + "ccmpo", "ccmpno", "ccmpb", "ccmpnb", "ccmpz", "ccmpnz", + "ccmpbe", "ccmpnbe", "ccmps", "ccmpns", "ccmpt", "ccmpf", + "ccmpl", "ccmpnl", "ccmple", "ccmpnle"}; + static const char *const ctest_names[] = { + "ctesto", "ctestno", "ctestb", "ctestnb", "ctestz", "ctestnz", + "ctestbe", "ctestnbe", "ctests", "ctestns", "ctestt", "ctestf", + "ctestl", "ctestnl", "ctestle", "ctestnle"}; + static const char *const dfvs[] = { + "", "cf", "zf", "zf,cf", "sf", "sf,cf", + "sf,zf", "sf,zf,cf", "of", "of,cf", "of,zf", "of,zf,cf", + "of,sf", "of,sf,cf", "of,sf,zf", "of,sf,zf,cf"}; + unsigned op = MCInst_getOpcode(in), i, n, idx; + bool mem, rmfirst, imm, ctest; + x86_reg rr, rm = X86_REG_INVALID, seg = X86_REG_INVALID; + x86_feature_memory m; + uint8_t w, dfv; + int64_t iv; + cs_detail *d; + cs_x86 *x; + ctest = + op >= X86_FEATURE_APX_CTEST_BASE && op < X86_FEATURE_APX_CTEST_BASE + 16; + if (!ctest && + (op < X86_FEATURE_APX_CCMP_BASE || op >= X86_FEATURE_APX_CCMP_BASE + 16)) + return false; + idx = op - (ctest ? X86_FEATURE_APX_CTEST_BASE : X86_FEATURE_APX_CCMP_BASE); + mem = MCOperand_getImm(MCInst_getOperand(in, 0)) != 0; + rmfirst = MCOperand_getImm(MCInst_getOperand(in, 1)) != 0; + rr = (x86_reg)MCOperand_getImm(MCInst_getOperand(in, 2)); + memset(&m, 0, sizeof(m)); + if (mem) { + if (MCInst_getNumOperands(in) != 13 || !get_feature_memory(in, 3, &m)) + return false; + seg = (x86_reg)MCOperand_getImm(MCInst_getOperand(in, 7)); + imm = MCOperand_getImm(MCInst_getOperand(in, 9)) != 0; + iv = MCOperand_getImm(MCInst_getOperand(in, 10)); + w = (uint8_t)MCOperand_getImm(MCInst_getOperand(in, 11)); + dfv = (uint8_t)MCOperand_getImm(MCInst_getOperand(in, 12)); + } else { + if (MCInst_getNumOperands(in) != 8) + return false; + rm = (x86_reg)MCOperand_getImm(MCInst_getOperand(in, 3)); + imm = MCOperand_getImm(MCInst_getOperand(in, 4)) != 0; + iv = MCOperand_getImm(MCInst_getOperand(in, 5)); + w = (uint8_t)MCOperand_getImm(MCInst_getOperand(in, 6)); + dfv = (uint8_t)MCOperand_getImm(MCInst_getOperand(in, 7)); + } + if (w != 1 && w != 2 && w != 4 && w != 8) + return false; + if (att) + SStream_concat(s, "%s%c\t{dfv=%s} ", + (ctest ? ctest_names : ccmp_names)[idx], + w == 1 ? 'b' + : w == 2 ? 'w' + : w == 4 ? 'l' + : 'q', + dfvs[dfv]); + else + SStream_concat(s, "%s\t{dfv=%s} ", (ctest ? ctest_names : ccmp_names)[idx], + dfvs[dfv]); + n = 2; + for (i = 0; i < n; i++) { + unsigned k = att ? 1 - i : i; + bool isrm = imm ? k == 0 : (rmfirst ? k == 0 : k == 1); + if (i) + SStream_concat0(s, ", "); + if (!isrm) { + if (imm) + print_apx_scalar_immediate(in, s, iv, w, att); + else + SStream_concat(s, att ? "%%%s" : "%s", X86_reg_name((csh)in->csh, rr)); + } else if (mem) { + if (!att) + SStream_concat0(s, w == 1 ? "byte ptr " + : w == 2 ? "word ptr " + : w == 4 ? "dword ptr " + : "qword ptr "); + if (seg != X86_REG_INVALID) + SStream_concat(s, att ? "%%%s:" : "%s:", feature_register_name(seg)); + if (!print_feature_memory(s, &m, att)) + return false; + } else + SStream_concat(s, att ? "%%%s" : "%s", X86_reg_name((csh)in->csh, rm)); + } + if (!in->flat_insn->detail) + return true; + d = in->flat_insn->detail; + x = &d->x86; + for (i = 0; i < n; i++) { + unsigned k = att ? 1 - i : i; + bool isrm = imm ? k == 0 : (rmfirst ? k == 0 : k == 1); + cs_x86_op *o = &x->operands[i]; + if (!isrm) { + if (imm) { + o->type = X86_OP_IMM; + o->imm = iv; + o->size = w; + o->access = CS_AC_READ; + } else { + o->type = X86_OP_REG; + o->reg = rr; + o->size = w; + o->access = CS_AC_READ; + } + } else if (mem) { + set_feature_memory_operand(o, &m, w, CS_AC_READ); + o->mem.segment = seg; + } else { + o->type = X86_OP_REG; + o->reg = rm; + o->size = w; + o->access = CS_AC_READ; + } + } + x->op_count = 2; + d->regs_read[d->regs_read_count++] = X86_REG_EFLAGS; + d->regs_write[d->regs_write_count++] = X86_REG_EFLAGS; + x->eflags = ctest ? (X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | + X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | + X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF) + : (X86_EFLAGS_MODIFY_OF | X86_EFLAGS_MODIFY_SF | + X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_MODIFY_AF | + X86_EFLAGS_MODIFY_PF | X86_EFLAGS_MODIFY_CF); + return true; } static bool print_apx_kmov(MCInst*in,SStream*s,bool att) @@ -5354,16 +6650,189 @@ static bool print_apx_bls(MCInst *instr, SStream *s, bool att) return true; } -static bool print_apx_unary(MCInst *instr, SStream *s, bool att) -{ - unsigned op=MCInst_getOpcode(instr); const char *mn; uint64_t flags; const MCOperand *d,*mf,*wo,*ndo,*nfo; bool mem,nd,nf; uint8_t w,i,count; x86_reg dst,src=X86_REG_INVALID,seg=X86_REG_INVALID; x86_feature_memory m; cs_x86 *x; cs_detail *detail; - switch(op){case X86_FEATURE_APX_INC:mn="inc";flags=X86_EFLAGS_MODIFY_OF|X86_EFLAGS_MODIFY_SF|X86_EFLAGS_MODIFY_ZF|X86_EFLAGS_MODIFY_AF|X86_EFLAGS_MODIFY_PF;break;case X86_FEATURE_APX_DEC:mn="dec";flags=X86_EFLAGS_MODIFY_OF|X86_EFLAGS_MODIFY_SF|X86_EFLAGS_MODIFY_ZF|X86_EFLAGS_MODIFY_AF|X86_EFLAGS_MODIFY_PF;break;case X86_FEATURE_APX_NEG:mn="neg";flags=X86_EFLAGS_MODIFY_OF|X86_EFLAGS_MODIFY_SF|X86_EFLAGS_MODIFY_ZF|X86_EFLAGS_MODIFY_AF|X86_EFLAGS_MODIFY_PF|X86_EFLAGS_MODIFY_CF;break;case X86_FEATURE_APX_NOT:mn="not";flags=0;break;case X86_FEATURE_APX_MUL:mn="mul";flags=X86_EFLAGS_MODIFY_OF|X86_EFLAGS_UNDEFINED_SF|X86_EFLAGS_UNDEFINED_ZF|X86_EFLAGS_UNDEFINED_AF|X86_EFLAGS_UNDEFINED_PF|X86_EFLAGS_MODIFY_CF;break;case X86_FEATURE_APX_IMUL_ONE:mn="imul";flags=X86_EFLAGS_MODIFY_OF|X86_EFLAGS_UNDEFINED_SF|X86_EFLAGS_UNDEFINED_ZF|X86_EFLAGS_UNDEFINED_AF|X86_EFLAGS_UNDEFINED_PF|X86_EFLAGS_MODIFY_CF;break;case X86_FEATURE_APX_DIV:mn="div";flags=X86_EFLAGS_UNDEFINED_OF|X86_EFLAGS_UNDEFINED_SF|X86_EFLAGS_UNDEFINED_ZF|X86_EFLAGS_UNDEFINED_AF|X86_EFLAGS_UNDEFINED_PF|X86_EFLAGS_UNDEFINED_CF;break;case X86_FEATURE_APX_IDIV:mn="idiv";flags=X86_EFLAGS_UNDEFINED_OF|X86_EFLAGS_UNDEFINED_SF|X86_EFLAGS_UNDEFINED_ZF|X86_EFLAGS_UNDEFINED_AF|X86_EFLAGS_UNDEFINED_PF|X86_EFLAGS_UNDEFINED_CF;break;default:return false;} - if(MCInst_getNumOperands(instr)<6)return false; d=MCInst_getOperand(instr,0);mf=MCInst_getOperand(instr,1);if(!MCOperand_isImm(d)||!MCOperand_isImm(mf))return false;dst=(x86_reg)MCOperand_getImm(d);mem=MCOperand_getImm(mf)!=0;memset(&m,0,sizeof(m)); - if(mem){const MCOperand *so;if(MCInst_getNumOperands(instr)!=11||!get_feature_memory(instr,2,&m))return false;so=MCInst_getOperand(instr,6);wo=MCInst_getOperand(instr,8);ndo=MCInst_getOperand(instr,9);nfo=MCInst_getOperand(instr,10);if(!MCOperand_isImm(so))return false;seg=(x86_reg)MCOperand_getImm(so);}else{const MCOperand *ro;if(MCInst_getNumOperands(instr)!=6)return false;ro=MCInst_getOperand(instr,2);wo=MCInst_getOperand(instr,3);ndo=MCInst_getOperand(instr,4);nfo=MCInst_getOperand(instr,5);if(!MCOperand_isImm(ro))return false;src=(x86_reg)MCOperand_getImm(ro);} - if(!MCOperand_isImm(wo)||!MCOperand_isImm(ndo)||!MCOperand_isImm(nfo))return false;w=(uint8_t)MCOperand_getImm(wo);nd=MCOperand_getImm(ndo)!=0;nf=MCOperand_getImm(nfo)!=0;if((w!=1&&w!=2&&w!=4&&w!=8)||(nd?dst==X86_REG_INVALID:dst!=X86_REG_INVALID))return false; - if(nf)SStream_concat0(s,"{nf}|");if(att)SStream_concat(s,"%s%c\t",mn,w==1?'b':w==2?'w':w==4?'l':'q');else SStream_concat(s,"%s\t",mn);count=nd?2:1; - for(i=0;icsh,dst);if(!n)return false;SStream_concat(s,att?"%%%s":"%s",n);}else if(mem){if(!att)SStream_concat0(s,w==1?"byte ptr ":w==2?"word ptr ":w==4?"dword ptr ":"qword ptr ");if(seg!=X86_REG_INVALID)SStream_concat(s,att?"%%%s:":"%s:",feature_register_name(seg));if(!print_feature_memory(s,&m,att))return false;}else{const char*n=X86_reg_name((csh)instr->csh,src);if(!n)return false;SStream_concat(s,att?"%%%s":"%s",n);}} - if(!instr->flat_insn->detail)return true;detail=instr->flat_insn->detail;x=&detail->x86;for(i=0;ioperands[i];if(isdst){o->type=X86_OP_REG;o->reg=dst;o->size=w;o->access=CS_AC_WRITE;}else if(mem){set_feature_memory_operand(o,&m,w,a);o->mem.segment=seg;}else{o->type=X86_OP_REG;o->reg=src;o->size=w;o->access=a;}}x->op_count=count;if(op==X86_FEATURE_APX_MUL||op==X86_FEATURE_APX_IMUL_ONE||op==X86_FEATURE_APX_DIV||op==X86_FEATURE_APX_IDIV){x86_reg lo=w==1?X86_REG_AL:w==2?X86_REG_AX:w==4?X86_REG_EAX:X86_REG_RAX;x86_reg hi=w==1?X86_REG_AH:w==2?X86_REG_DX:w==4?X86_REG_EDX:X86_REG_RDX;detail->regs_read[detail->regs_read_count++]=lo;if(op==X86_FEATURE_APX_DIV||op==X86_FEATURE_APX_IDIV)detail->regs_read[detail->regs_read_count++]=hi;detail->regs_write[detail->regs_write_count++]=lo;detail->regs_write[detail->regs_write_count++]=hi;}if(!nf&&flags){detail->regs_write[detail->regs_write_count++]=X86_REG_EFLAGS;x->eflags=flags;}return true; +static bool print_apx_unary(MCInst *instr, SStream *s, bool att) { + unsigned op = MCInst_getOpcode(instr); + const char *mn; + uint64_t flags; + const MCOperand *d, *mf, *wo, *ndo, *nfo; + bool mem, nd, nf; + uint8_t w, i, count; + x86_reg dst, src = X86_REG_INVALID, seg = X86_REG_INVALID; + x86_feature_memory m; + cs_x86 *x; + cs_detail *detail; + switch (op) { + case X86_FEATURE_APX_INC: + mn = "inc"; + flags = X86_EFLAGS_MODIFY_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | + X86_EFLAGS_MODIFY_AF | X86_EFLAGS_MODIFY_PF; + break; + case X86_FEATURE_APX_DEC: + mn = "dec"; + flags = X86_EFLAGS_MODIFY_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | + X86_EFLAGS_MODIFY_AF | X86_EFLAGS_MODIFY_PF; + break; + case X86_FEATURE_APX_NEG: + mn = "neg"; + flags = X86_EFLAGS_MODIFY_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | + X86_EFLAGS_MODIFY_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_MODIFY_CF; + break; + case X86_FEATURE_APX_NOT: + mn = "not"; + flags = 0; + break; + case X86_FEATURE_APX_MUL: + mn = "mul"; + flags = X86_EFLAGS_MODIFY_OF | X86_EFLAGS_UNDEFINED_SF | + X86_EFLAGS_UNDEFINED_ZF | X86_EFLAGS_UNDEFINED_AF | + X86_EFLAGS_UNDEFINED_PF | X86_EFLAGS_MODIFY_CF; + break; + case X86_FEATURE_APX_IMUL_ONE: + mn = "imul"; + flags = X86_EFLAGS_MODIFY_OF | X86_EFLAGS_UNDEFINED_SF | + X86_EFLAGS_UNDEFINED_ZF | X86_EFLAGS_UNDEFINED_AF | + X86_EFLAGS_UNDEFINED_PF | X86_EFLAGS_MODIFY_CF; + break; + case X86_FEATURE_APX_DIV: + mn = "div"; + flags = X86_EFLAGS_UNDEFINED_OF | X86_EFLAGS_UNDEFINED_SF | + X86_EFLAGS_UNDEFINED_ZF | X86_EFLAGS_UNDEFINED_AF | + X86_EFLAGS_UNDEFINED_PF | X86_EFLAGS_UNDEFINED_CF; + break; + case X86_FEATURE_APX_IDIV: + mn = "idiv"; + flags = X86_EFLAGS_UNDEFINED_OF | X86_EFLAGS_UNDEFINED_SF | + X86_EFLAGS_UNDEFINED_ZF | X86_EFLAGS_UNDEFINED_AF | + X86_EFLAGS_UNDEFINED_PF | X86_EFLAGS_UNDEFINED_CF; + break; + default: + return false; + } + if (MCInst_getNumOperands(instr) < 6) + return false; + d = MCInst_getOperand(instr, 0); + mf = MCInst_getOperand(instr, 1); + if (!MCOperand_isImm(d) || !MCOperand_isImm(mf)) + return false; + dst = (x86_reg)MCOperand_getImm(d); + mem = MCOperand_getImm(mf) != 0; + memset(&m, 0, sizeof(m)); + if (mem) { + const MCOperand *so; + if (MCInst_getNumOperands(instr) != 11 || !get_feature_memory(instr, 2, &m)) + return false; + so = MCInst_getOperand(instr, 6); + wo = MCInst_getOperand(instr, 8); + ndo = MCInst_getOperand(instr, 9); + nfo = MCInst_getOperand(instr, 10); + if (!MCOperand_isImm(so)) + return false; + seg = (x86_reg)MCOperand_getImm(so); + } else { + const MCOperand *ro; + if (MCInst_getNumOperands(instr) != 6) + return false; + ro = MCInst_getOperand(instr, 2); + wo = MCInst_getOperand(instr, 3); + ndo = MCInst_getOperand(instr, 4); + nfo = MCInst_getOperand(instr, 5); + if (!MCOperand_isImm(ro)) + return false; + src = (x86_reg)MCOperand_getImm(ro); + } + if (!MCOperand_isImm(wo) || !MCOperand_isImm(ndo) || !MCOperand_isImm(nfo)) + return false; + w = (uint8_t)MCOperand_getImm(wo); + nd = MCOperand_getImm(ndo) != 0; + nf = MCOperand_getImm(nfo) != 0; + if ((w != 1 && w != 2 && w != 4 && w != 8) || + (nd ? dst == X86_REG_INVALID : dst != X86_REG_INVALID)) + return false; + if (nf) + SStream_concat0(s, "{nf}|"); + if (att) + SStream_concat(s, "%s%c\t", mn, + w == 1 ? 'b' + : w == 2 ? 'w' + : w == 4 ? 'l' + : 'q'); + else + SStream_concat(s, "%s\t", mn); + count = nd ? 2 : 1; + for (i = 0; i < count; ++i) { + bool isdst = nd && (att ? i == 1 : i == 0); + if (i) + SStream_concat0(s, ", "); + if (isdst) { + const char *n = X86_reg_name((csh)instr->csh, dst); + if (!n) + return false; + SStream_concat(s, att ? "%%%s" : "%s", n); + } else if (mem) { + if (!att) + SStream_concat0(s, w == 1 ? "byte ptr " + : w == 2 ? "word ptr " + : w == 4 ? "dword ptr " + : "qword ptr "); + if (seg != X86_REG_INVALID) + SStream_concat(s, att ? "%%%s:" : "%s:", feature_register_name(seg)); + if (!print_feature_memory(s, &m, att)) + return false; + } else { + const char *n = X86_reg_name((csh)instr->csh, src); + if (!n) + return false; + SStream_concat(s, att ? "%%%s" : "%s", n); + } + } + if (!instr->flat_insn->detail) + return true; + detail = instr->flat_insn->detail; + x = &detail->x86; + for (i = 0; i < count; ++i) { + bool isdst = nd && (att ? i == 1 : i == 0); + bool implicit = op == X86_FEATURE_APX_MUL || + op == X86_FEATURE_APX_IMUL_ONE || + op == X86_FEATURE_APX_DIV || op == X86_FEATURE_APX_IDIV; + cs_ac_type a = (nd || implicit) ? CS_AC_READ : CS_AC_READ | CS_AC_WRITE; + cs_x86_op *o = &x->operands[i]; + if (isdst) { + o->type = X86_OP_REG; + o->reg = dst; + o->size = w; + o->access = CS_AC_WRITE; + } else if (mem) { + set_feature_memory_operand(o, &m, w, a); + o->mem.segment = seg; + } else { + o->type = X86_OP_REG; + o->reg = src; + o->size = w; + o->access = a; + } + } + x->op_count = count; + if (op == X86_FEATURE_APX_MUL || op == X86_FEATURE_APX_IMUL_ONE || + op == X86_FEATURE_APX_DIV || op == X86_FEATURE_APX_IDIV) { + x86_reg lo = w == 1 ? X86_REG_AL + : w == 2 ? X86_REG_AX + : w == 4 ? X86_REG_EAX + : X86_REG_RAX; + x86_reg hi = w == 1 ? X86_REG_AH + : w == 2 ? X86_REG_DX + : w == 4 ? X86_REG_EDX + : X86_REG_RDX; + detail->regs_read[detail->regs_read_count++] = lo; + if (op == X86_FEATURE_APX_DIV || op == X86_FEATURE_APX_IDIV) + detail->regs_read[detail->regs_read_count++] = hi; + detail->regs_write[detail->regs_write_count++] = lo; + detail->regs_write[detail->regs_write_count++] = hi; + } + if (!nf && flags) { + detail->regs_write[detail->regs_write_count++] = X86_REG_EFLAGS; + x->eflags = flags; + } + return true; } static bool print_apx_imul(MCInst *instr, SStream *stream, bool att_syntax) diff --git a/tests/unit/x86_apx_cmov.c b/tests/unit/x86_apx_cmov.c index 895a6c3174..0ae7aa50db 100644 --- a/tests/unit/x86_apx_cmov.c +++ b/tests/unit/x86_apx_cmov.c @@ -102,7 +102,7 @@ static void encode_evex(uint8_t code[6], unsigned int cc, bool nd, bool nf, code[5] = 0xc0 | ((reg & 7) << 3) | (rm & 7); } -static bool has_register(const cs_regs registers, uint8_t count, x86_reg reg) +static bool has_register(const uint16_t *registers, uint8_t count, x86_reg reg) { uint8_t i; diff --git a/tests/unit/x86_apx_evex_convert.c b/tests/unit/x86_apx_evex_convert.c index c8c31e0765..4cd15f5a24 100644 --- a/tests/unit/x86_apx_evex_convert.c +++ b/tests/unit/x86_apx_evex_convert.c @@ -10,33 +10,88 @@ static bool one(csh h,const uint8_t*b,size_t n,unsigned id,const char*m,const ch cs_free(i,ok||i?1:0);return ok; } -int main(void) -{ - const uint8_t ml16[]={0x62,0xec,0x7d,0x08,0x60,0xd3}; - const uint8_t ms32[]={0x62,0xec,0x7c,0x08,0x61,0xda}; - const uint8_t mlm[]={0x64,0x62,0x0c,0x7c,0x08,0x60,0x54,0xb5,0x20}; - const uint8_t cb[]={0x62,0xec,0xfc,0x08,0xf0,0xd3}; - const uint8_t cw[]={0x62,0xec,0x7d,0x08,0xf1,0xd3}; - const uint8_t cq[]={0x64,0x62,0x0c,0xfc,0x08,0xf1,0x54,0xb5,0x20}; - uint8_t bad[]={0x62,0xec,0x7c,0x08,0x60,0xd3};csh h;cs_insn*i=NULL;bool ok=true; - if(cs_open(CS_ARCH_X86,CS_MODE_64,&h))return 1;cs_option(h,CS_OPT_DETAIL,CS_OPT_ON); - ok&=one(h,ml16,sizeof(ml16),X86_INS_MOVBE,"movbe","r18w, r19w"); - ok&=one(h,ms32,sizeof(ms32),X86_INS_MOVBE,"movbe","r18d, r19d"); - if(cs_disasm(h,ms32,sizeof(ms32),0,1,&i)!=1)ok=false;else{const cs_x86*x=&i->detail->x86;ok&=x->operands[0].reg==X86_REG_R18D&&x->operands[0].access==CS_AC_WRITE&&x->operands[1].reg==X86_REG_R19D&&x->operands[1].access==CS_AC_READ;cs_free(i,1);i=NULL;} - ok&=one(h,mlm,sizeof(mlm),X86_INS_MOVBE,"movbe","r26d, dword ptr fs:[r29 + r14*4 + 0x20]"); - ok&=one(h,cb,sizeof(cb),X86_INS_CRC32,"crc32","r18, r19b"); - ok&=one(h,cw,sizeof(cw),X86_INS_CRC32,"crc32","r18d, r19w"); - ok&=one(h,cq,sizeof(cq),X86_INS_CRC32,"crc32","r26, qword ptr fs:[r29 + r14*4 + 0x20]"); - if(cs_disasm(h,cq,sizeof(cq),0,1,&i)!=1)ok=false;else{const cs_x86*x=&i->detail->x86;ok&=x->op_count==2&&x->operands[0].reg==X86_REG_R26&&x->operands[0].access==CS_AC_READ_WRITE&&x->operands[1].type==X86_OP_MEM&&x->operands[1].access==CS_AC_READ&&x->operands[1].mem.segment==X86_REG_FS&&x->operands[1].mem.base==X86_REG_R29&&x->operands[1].mem.index==X86_REG_R14;cs_free(i,1);i=NULL;} - /* W selects 64-bit operands over 66, as XED decodes them. */ - {const uint8_t mw[]={0x62,0xec,0xfd,0x08,0x60,0xd3};const uint8_t cw66[]={0x62,0xec,0xfd,0x08,0xf1,0xd3}; - ok&=one(h,mw,sizeof(mw),X86_INS_MOVBE,"movbe","r18, r19"); - ok&=one(h,cw66,sizeof(cw66),X86_INS_CRC32,"crc32","r18, r19");} - cs_option(h,CS_OPT_SYNTAX,CS_OPT_SYNTAX_ATT); - ok&=one(h,cq,sizeof(cq),X86_INS_CRC32,"crc32q","%fs:0x20(%r29,%r14,4), %r26"); - cs_option(h,CS_OPT_SYNTAX,CS_OPT_SYNTAX_INTEL); - for(unsigned k=0;k<4;k++){bad[3]=(uint8_t[]){0x00,0x0c,0x18,0x28}[k];if(cs_disasm(h,bad,sizeof(bad),0,1,&i)){ok=false;cs_free(i,1);i=NULL;}} - bad[2]=0x74;bad[3]=8;if(cs_disasm(h,bad,sizeof(bad),0,1,&i)){ok=false;cs_free(i,1);i=NULL;} - bad[2]=0x7d;bad[3]=8;bad[4]=0xf0;if(cs_disasm(h,bad,sizeof(bad),0,1,&i)){ok=false;cs_free(i,1);} - cs_close(&h);if(!ok)fprintf(stderr,"APX conversion failure\n");return ok?0:1; +int main(void) { + const uint8_t ml16[] = {0x62, 0xec, 0x7d, 0x08, 0x60, 0xd3}; + const uint8_t ms32[] = {0x62, 0xec, 0x7c, 0x08, 0x61, 0xda}; + const uint8_t mlm[] = {0x64, 0x62, 0x0c, 0x7c, 0x08, 0x60, 0x54, 0xb5, 0x20}; + const uint8_t cb[] = {0x62, 0xec, 0xfc, 0x08, 0xf0, 0xd3}; + const uint8_t cw[] = {0x62, 0xec, 0x7d, 0x08, 0xf1, 0xd3}; + const uint8_t cq[] = {0x64, 0x62, 0x0c, 0xfc, 0x08, 0xf1, 0x54, 0xb5, 0x20}; + uint8_t bad[] = {0x62, 0xec, 0x7c, 0x08, 0x60, 0xd3}; + csh h; + cs_insn *i = NULL; + bool ok = true; + if (cs_open(CS_ARCH_X86, CS_MODE_64, &h)) + return 1; + cs_option(h, CS_OPT_DETAIL, CS_OPT_ON); + ok &= one(h, ml16, sizeof(ml16), X86_INS_MOVBE, "movbe", "r18w, r19w"); + ok &= one(h, ms32, sizeof(ms32), X86_INS_MOVBE, "movbe", "r18d, r19d"); + if (cs_disasm(h, ms32, sizeof(ms32), 0, 1, &i) != 1) + ok = false; + else { + const cs_x86 *x = &i->detail->x86; + ok &= x->operands[0].reg == X86_REG_R18D && + x->operands[0].access == CS_AC_WRITE && + x->operands[1].reg == X86_REG_R19D && + x->operands[1].access == CS_AC_READ; + cs_free(i, 1); + i = NULL; + } + ok &= one(h, mlm, sizeof(mlm), X86_INS_MOVBE, "movbe", + "r26d, dword ptr fs:[r29 + r14*4 + 0x20]"); + ok &= one(h, cb, sizeof(cb), X86_INS_CRC32, "crc32", "r18, r19b"); + ok &= one(h, cw, sizeof(cw), X86_INS_CRC32, "crc32", "r18d, r19w"); + ok &= one(h, cq, sizeof(cq), X86_INS_CRC32, "crc32", + "r26, qword ptr fs:[r29 + r14*4 + 0x20]"); + if (cs_disasm(h, cq, sizeof(cq), 0, 1, &i) != 1) + ok = false; + else { + const cs_x86 *x = &i->detail->x86; + ok &= x->op_count == 2 && x->operands[0].reg == X86_REG_R26 && + x->operands[0].access == CS_AC_READ_WRITE && + x->operands[1].type == X86_OP_MEM && + x->operands[1].access == CS_AC_READ && + x->operands[1].mem.segment == X86_REG_FS && + x->operands[1].mem.base == X86_REG_R29 && + x->operands[1].mem.index == X86_REG_R14; + cs_free(i, 1); + i = NULL; + } + /* W selects 64-bit operands over 66, as XED decodes them. */ + { + const uint8_t mw[] = {0x62, 0xec, 0xfd, 0x08, 0x60, 0xd3}; + const uint8_t cw66[] = {0x62, 0xec, 0xfd, 0x08, 0xf1, 0xd3}; + ok &= one(h, mw, sizeof(mw), X86_INS_MOVBE, "movbe", "r18, r19"); + ok &= one(h, cw66, sizeof(cw66), X86_INS_CRC32, "crc32", "r18, r19"); + } + cs_option(h, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); + ok &= one(h, cq, sizeof(cq), X86_INS_CRC32, "crc32q", + "%fs:0x20(%r29,%r14,4), %r26"); + cs_option(h, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL); + for (unsigned k = 0; k < 4; k++) { + bad[3] = (uint8_t[]){0x00, 0x0c, 0x18, 0x28}[k]; + if (cs_disasm(h, bad, sizeof(bad), 0, 1, &i)) { + ok = false; + cs_free(i, 1); + i = NULL; + } + } + bad[2] = 0x74; + bad[3] = 8; + if (cs_disasm(h, bad, sizeof(bad), 0, 1, &i)) { + ok = false; + cs_free(i, 1); + i = NULL; + } + bad[2] = 0x7d; + bad[3] = 8; + bad[4] = 0xf0; + if (cs_disasm(h, bad, sizeof(bad), 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + cs_close(&h); + if (!ok) + fprintf(stderr, "APX conversion failure\n"); + return ok ? 0 : 1; } diff --git a/tests/unit/x86_apx_evex_duplicate_prefix.c b/tests/unit/x86_apx_evex_duplicate_prefix.c index 0dcd81eccf..539eab66fd 100644 --- a/tests/unit/x86_apx_evex_duplicate_prefix.c +++ b/tests/unit/x86_apx_evex_duplicate_prefix.c @@ -19,7 +19,7 @@ static bool decodes(csh handle, const uint8_t *code, size_t size, { cs_insn *instruction = NULL; size_t count = cs_disasm(handle, code, size, 0, 1, &instruction); - char actual[160] = ""; + char actual[sizeof(instruction->mnemonic) + sizeof(instruction->op_str)] = ""; bool ok; if (count == 1) diff --git a/tests/unit/x86_apx_evex_invalidate.c b/tests/unit/x86_apx_evex_invalidate.c index 63358020af..ffc78ade3d 100644 --- a/tests/unit/x86_apx_evex_invalidate.c +++ b/tests/unit/x86_apx_evex_invalidate.c @@ -21,19 +21,58 @@ static bool ck(csh h,const uint8_t*b,size_t n,unsigned id,const char*mn,const ch cs_free(i,1);return ok; } -int main(void) -{ - csh h;cs_insn*i=NULL;bool ok=true;uint8_t b[]={0x62,0xec,0x7e,8,0xf0,0x11}; - const unsigned ids[]={X86_INS_INVEPT,X86_INS_INVVPID,X86_INS_INVPCID}; - const char*mn[]={"invept","invvpid","invpcid"}; - if(cs_open(CS_ARCH_X86,CS_MODE_64,&h))return 1;cs_option(h,CS_OPT_DETAIL,CS_OPT_ON); - for(unsigned k=0;k<3;k++){b[4]=(uint8_t)(0xf0+k);ok&=ck(h,b,6,ids[k],mn[k], - k==0?"r18, xmmword ptr [r17]":k==1?"r18, xmmword ptr [r17]":"r18, xmmword ptr [r17]");} - b[2]=0xfe;b[4]=0xf0;ok&=ck(h,b,6,X86_INS_INVEPT,"invept","r18, xmmword ptr [r17]"); - {const uint8_t a[]={0x64,0x67,0x62,0xec,0x7a,8,0xf2,0x11}; - ok&=ck(h,a,sizeof(a),X86_INS_INVPCID,"invpcid","r18, xmmword ptr fs:[r17d]"); - cs_option(h,CS_OPT_SYNTAX,CS_OPT_SYNTAX_ATT);ok&=ck(h,a,sizeof(a),X86_INS_INVPCID, - "invpcid","%fs:(%r17d), %r18");cs_option(h,CS_OPT_SYNTAX,CS_OPT_SYNTAX_INTEL);} - {uint8_t x[]={0x62,0xec,0x7e,8,0xf0,0xd1};if(cs_disasm(h,x,6,0,1,&i)){ok=false;cs_free(i,1);}x[5]=0x11;x[3]=9;if(cs_disasm(h,x,6,0,1,&i)){ok=false;cs_free(i,1);}x[3]=8;x[2]=0x7f;if(cs_disasm(h,x,6,0,1,&i)){ok=false;cs_free(i,1);}x[2]=0x76;if(cs_disasm(h,x,6,0,1,&i)){ok=false;cs_free(i,1);}} - cs_close(&h);return ok?0:1; +int main(void) { + csh h; + cs_insn *i = NULL; + bool ok = true; + uint8_t b[] = {0x62, 0xec, 0x7e, 8, 0xf0, 0x11}; + const unsigned ids[] = {X86_INS_INVEPT, X86_INS_INVVPID, X86_INS_INVPCID}; + const char *mn[] = {"invept", "invvpid", "invpcid"}; + if (cs_open(CS_ARCH_X86, CS_MODE_64, &h)) + return 1; + cs_option(h, CS_OPT_DETAIL, CS_OPT_ON); + for (unsigned k = 0; k < 3; k++) { + b[4] = (uint8_t)(0xf0 + k); + ok &= ck(h, b, 6, ids[k], mn[k], + k == 0 ? "r18, xmmword ptr [r17]" + : k == 1 ? "r18, xmmword ptr [r17]" + : "r18, xmmword ptr [r17]"); + } + b[2] = 0xfe; + b[4] = 0xf0; + ok &= ck(h, b, 6, X86_INS_INVEPT, "invept", "r18, xmmword ptr [r17]"); + { + const uint8_t a[] = {0x64, 0x67, 0x62, 0xec, 0x7a, 8, 0xf2, 0x11}; + ok &= ck(h, a, sizeof(a), X86_INS_INVPCID, "invpcid", + "r18, xmmword ptr fs:[r17d]"); + cs_option(h, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); + ok &= ck(h, a, sizeof(a), X86_INS_INVPCID, "invpcid", "%fs:(%r17d), %r18"); + cs_option(h, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL); + } + { + uint8_t x[] = {0x62, 0xec, 0x7e, 8, 0xf0, 0xd1}; + if (cs_disasm(h, x, 6, 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + x[5] = 0x11; + x[3] = 9; + if (cs_disasm(h, x, 6, 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + x[3] = 8; + x[2] = 0x7f; + if (cs_disasm(h, x, 6, 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + x[2] = 0x76; + if (cs_disasm(h, x, 6, 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + } + cs_close(&h); + return ok ? 0 : 1; } diff --git a/tests/unit/x86_apx_evex_kmov.c b/tests/unit/x86_apx_evex_kmov.c index 4d5312751d..e87322ea5f 100644 --- a/tests/unit/x86_apx_evex_kmov.c +++ b/tests/unit/x86_apx_evex_kmov.c @@ -25,42 +25,114 @@ static bool ck(csh h,const uint8_t*b,size_t n,unsigned id,const char*mn, cs_free(i,1);return ok; } -int main(void) -{ - csh h;cs_insn*i=NULL;bool ok=true; - const uint8_t kk[][6]={{0x62,0xf1,0x7d,8,0x90,0xd9},{0x62,0xf1,0x7c,8,0x90,0xd9}, - {0x62,0xf1,0xfd,8,0x90,0xd9},{0x62,0xf1,0xfc,8,0x90,0xd9}}; - const unsigned ids[]={X86_INS_KMOVB,X86_INS_KMOVW,X86_INS_KMOVD,X86_INS_KMOVQ}; - const char*mn[]={"kmovb","kmovw","kmovd","kmovq"};uint8_t sz[]={1,2,4,8}; - if(cs_open(CS_ARCH_X86,CS_MODE_64,&h))return 1;cs_option(h,CS_OPT_DETAIL,CS_OPT_ON); - for(unsigned k=0;k<4;k++)ok&=ck(h,kk[k],6,ids[k],mn[k],"k3, k1",sz[k],sz[k]); - {const uint8_t legacy[]={0xc5,0xf9,0x90,0xd9}; - ok&=ck(h,legacy,4,X86_INS_KMOVB,"kmovb","k3, k1",1,1);} - {const uint8_t b[]={0x62,0xf9,0x7d,8,0x92,0xd9};ok&=ck(h,b,6,X86_INS_KMOVB,"kmovb","k3, r17d",1,4);} - {const uint8_t b[]={0x62,0xe1,0x7d,8,0x93,0xcb};ok&=ck(h,b,6,X86_INS_KMOVB,"kmovb","r17d, k3",4,1);} - {const uint8_t b[]={0x62,0xf9,0x7f,8,0x92,0xd9};ok&=ck(h,b,6,X86_INS_KMOVD,"kmovd","k3, r17d",4,4);} - {const uint8_t b[]={0x62,0xf9,0x7c,8,0x92,0xd9};ok&=ck(h,b,6,X86_INS_KMOVW,"kmovw","k3, r17d",2,4);} - {const uint8_t b[]={0x62,0xe1,0x7c,8,0x93,0xcb};ok&=ck(h,b,6,X86_INS_KMOVW,"kmovw","r17d, k3",4,2);} - {const uint8_t b[]={0x62,0xf9,0xff,8,0x92,0xd9};ok&=ck(h,b,6,X86_INS_KMOVQ,"kmovq","k3, r17",8,8);} - {uint8_t b[]={0x64,0x62,0xf9,0,8,0x90,0x11}; - const uint8_t p[]={0x7d,0x7c,0xfd,0xfc}; - const char*ld[]={"k2, byte ptr fs:[r17]","k2, word ptr fs:[r17]", - "k2, dword ptr fs:[r17]","k2, qword ptr fs:[r17]"}; - const char*st[]={"byte ptr fs:[r17], k3","word ptr fs:[r17], k3", - "dword ptr fs:[r17], k3","qword ptr fs:[r17], k3"}; - for(unsigned k=0;k<4;k++){b[3]=p[k];b[5]=0x90;b[6]=0x11; - ok&=ck(h,b,7,ids[k],mn[k],ld[k],sz[k],sz[k]); - b[5]=0x91;b[6]=0x19;ok&=ck(h,b,7,ids[k],mn[k],st[k],sz[k],sz[k]);}} - {const uint8_t b[]={0x64,0x62,0x99,0xf9,8,0x90,0x54,0xa5,0x20}; - ok&=ck(h,b,sizeof(b),X86_INS_KMOVD,"kmovd", - "k2, dword ptr fs:[r29 + r28*4 + 0x20]",4,4);} - {const uint8_t b[]={0x64,0x62,0x99,0xf9,8,0x91,0x5c,0xa5,0x20}; - ok&=ck(h,b,sizeof(b),X86_INS_KMOVD,"kmovd", - "dword ptr fs:[r29 + r28*4 + 0x20], k3",4,4);} - {const uint8_t b[]={0x67,0x64,0x62,0x99,0xf9,8,0x90,0x54,0xa5,0x20}; - ok&=ck(h,b,sizeof(b),X86_INS_KMOVD,"kmovd", - "k2, dword ptr fs:[r29d + r28d*4 + 0x20]",4,4);} - {const uint8_t b[]={0x62,0xf9,0xff,8,0x92,0xd9};cs_option(h,CS_OPT_SYNTAX,CS_OPT_SYNTAX_ATT);ok&=ck(h,b,6,X86_INS_KMOVQ,"kmovq","%r17, %k3",8,8);cs_option(h,CS_OPT_SYNTAX,CS_OPT_SYNTAX_INTEL);} - {uint8_t x[]={0x62,0xf9,0x7d,8,0x92,0x19};if(cs_disasm(h,x,6,0,1,&i)){ok=false;cs_free(i,1);}x[3]=9;x[5]=0xd9;if(cs_disasm(h,x,6,0,1,&i)){ok=false;cs_free(i,1);}x[3]=8;x[2]=0x79;if(cs_disasm(h,x,6,0,1,&i)){ok=false;cs_free(i,1);}x[2]=0x75;if(cs_disasm(h,x,6,0,1,&i)){ok=false;cs_free(i,1);}} - cs_close(&h);return ok?0:1; +int main(void) { + csh h; + cs_insn *i = NULL; + bool ok = true; + const uint8_t kk[][6] = {{0x62, 0xf1, 0x7d, 8, 0x90, 0xd9}, + {0x62, 0xf1, 0x7c, 8, 0x90, 0xd9}, + {0x62, 0xf1, 0xfd, 8, 0x90, 0xd9}, + {0x62, 0xf1, 0xfc, 8, 0x90, 0xd9}}; + const unsigned ids[] = {X86_INS_KMOVB, X86_INS_KMOVW, X86_INS_KMOVD, + X86_INS_KMOVQ}; + const char *mn[] = {"kmovb", "kmovw", "kmovd", "kmovq"}; + uint8_t sz[] = {1, 2, 4, 8}; + if (cs_open(CS_ARCH_X86, CS_MODE_64, &h)) + return 1; + cs_option(h, CS_OPT_DETAIL, CS_OPT_ON); + for (unsigned k = 0; k < 4; k++) + ok &= ck(h, kk[k], 6, ids[k], mn[k], "k3, k1", sz[k], sz[k]); + { + const uint8_t legacy[] = {0xc5, 0xf9, 0x90, 0xd9}; + ok &= ck(h, legacy, 4, X86_INS_KMOVB, "kmovb", "k3, k1", 1, 1); + } + { + const uint8_t b[] = {0x62, 0xf9, 0x7d, 8, 0x92, 0xd9}; + ok &= ck(h, b, 6, X86_INS_KMOVB, "kmovb", "k3, r17d", 1, 4); + } + { + const uint8_t b[] = {0x62, 0xe1, 0x7d, 8, 0x93, 0xcb}; + ok &= ck(h, b, 6, X86_INS_KMOVB, "kmovb", "r17d, k3", 4, 1); + } + { + const uint8_t b[] = {0x62, 0xf9, 0x7f, 8, 0x92, 0xd9}; + ok &= ck(h, b, 6, X86_INS_KMOVD, "kmovd", "k3, r17d", 4, 4); + } + { + const uint8_t b[] = {0x62, 0xf9, 0x7c, 8, 0x92, 0xd9}; + ok &= ck(h, b, 6, X86_INS_KMOVW, "kmovw", "k3, r17d", 2, 4); + } + { + const uint8_t b[] = {0x62, 0xe1, 0x7c, 8, 0x93, 0xcb}; + ok &= ck(h, b, 6, X86_INS_KMOVW, "kmovw", "r17d, k3", 4, 2); + } + { + const uint8_t b[] = {0x62, 0xf9, 0xff, 8, 0x92, 0xd9}; + ok &= ck(h, b, 6, X86_INS_KMOVQ, "kmovq", "k3, r17", 8, 8); + } + { + uint8_t b[] = {0x64, 0x62, 0xf9, 0, 8, 0x90, 0x11}; + const uint8_t p[] = {0x7d, 0x7c, 0xfd, 0xfc}; + const char *ld[] = {"k2, byte ptr fs:[r17]", "k2, word ptr fs:[r17]", + "k2, dword ptr fs:[r17]", "k2, qword ptr fs:[r17]"}; + const char *st[] = {"byte ptr fs:[r17], k3", "word ptr fs:[r17], k3", + "dword ptr fs:[r17], k3", "qword ptr fs:[r17], k3"}; + for (unsigned k = 0; k < 4; k++) { + b[3] = p[k]; + b[5] = 0x90; + b[6] = 0x11; + ok &= ck(h, b, 7, ids[k], mn[k], ld[k], sz[k], sz[k]); + b[5] = 0x91; + b[6] = 0x19; + ok &= ck(h, b, 7, ids[k], mn[k], st[k], sz[k], sz[k]); + } + } + { + const uint8_t b[] = {0x64, 0x62, 0x99, 0xf9, 8, 0x90, 0x54, 0xa5, 0x20}; + ok &= ck(h, b, sizeof(b), X86_INS_KMOVD, "kmovd", + "k2, dword ptr fs:[r29 + r28*4 + 0x20]", 4, 4); + } + { + const uint8_t b[] = {0x64, 0x62, 0x99, 0xf9, 8, 0x91, 0x5c, 0xa5, 0x20}; + ok &= ck(h, b, sizeof(b), X86_INS_KMOVD, "kmovd", + "dword ptr fs:[r29 + r28*4 + 0x20], k3", 4, 4); + } + { + const uint8_t b[] = {0x67, 0x64, 0x62, 0x99, 0xf9, + 8, 0x90, 0x54, 0xa5, 0x20}; + ok &= ck(h, b, sizeof(b), X86_INS_KMOVD, "kmovd", + "k2, dword ptr fs:[r29d + r28d*4 + 0x20]", 4, 4); + } + { + const uint8_t b[] = {0x62, 0xf9, 0xff, 8, 0x92, 0xd9}; + cs_option(h, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); + ok &= ck(h, b, 6, X86_INS_KMOVQ, "kmovq", "%r17, %k3", 8, 8); + cs_option(h, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL); + } + { + uint8_t x[] = {0x62, 0xf9, 0x7d, 8, 0x92, 0x19}; + if (cs_disasm(h, x, 6, 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + x[3] = 9; + x[5] = 0xd9; + if (cs_disasm(h, x, 6, 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + x[3] = 8; + x[2] = 0x79; + if (cs_disasm(h, x, 6, 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + x[2] = 0x75; + if (cs_disasm(h, x, 6, 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + } + cs_close(&h); + return ok ? 0 : 1; } diff --git a/tests/unit/x86_apx_evex_movrs.c b/tests/unit/x86_apx_evex_movrs.c index 69dce03d0b..2768127292 100644 --- a/tests/unit/x86_apx_evex_movrs.c +++ b/tests/unit/x86_apx_evex_movrs.c @@ -21,32 +21,70 @@ static bool ck(csh h,const uint8_t*b,size_t n,const char*mn,const char*ops, cs_free(i,1);return ok; } -int main(void) -{ - csh h;cs_insn*i=NULL;bool ok=true; - const uint8_t b8[]={0x64,0x62,0xec,0x7c,8,0x8a,0x11}; - const uint8_t b16[]={0x62,0xec,0x7d,8,0x8b,0x11}; - const uint8_t b32[]={0x67,0x62,0xec,0x7c,8,0x8b,0x11}; - const uint8_t b64[]={0x64,0x67,0x62,0xec,0xfc,8,0x8b,0x11}; - const uint8_t x4[]={0x64,0x62,0x0c,0x78,8,0x8b,0x54,0xa5,0x20}; - const uint8_t x4a32[]={0x67,0x64,0x62,0x0c,0x78,8,0x8b,0x54,0xa5,0x20}; - if(cs_open(CS_ARCH_X86,CS_MODE_64,&h))return 1;cs_option(h,CS_OPT_DETAIL,CS_OPT_ON); - ok&=ck(h,b8,sizeof(b8),"movrs","r18b, byte ptr fs:[r17]",X86_REG_R18B,1); - ok&=ck(h,b16,sizeof(b16),"movrs","r18w, word ptr [r17]",X86_REG_R18W,2); - ok&=ck(h,b32,sizeof(b32),"movrs","r18d, dword ptr [r17d]",X86_REG_R18D,4); - ok&=ck(h,b64,sizeof(b64),"movrs","r18, qword ptr fs:[r17d]",X86_REG_R18,8); - ok&=ck(h,x4,sizeof(x4),"movrs", - "r26d, dword ptr fs:[r29 + r28*4 + 0x20]",X86_REG_R26D,4); - ok&=ck(h,x4a32,sizeof(x4a32),"movrs", - "r26d, dword ptr fs:[r29d + r28d*4 + 0x20]",X86_REG_R26D,4); - cs_option(h,CS_OPT_SYNTAX,CS_OPT_SYNTAX_ATT); - ok&=ck(h,b64,sizeof(b64),"movrsq","%fs:(%r17d), %r18",X86_REG_R18,8); - cs_option(h,CS_OPT_SYNTAX,CS_OPT_SYNTAX_INTEL); - /* W selects 64-bit operands over 66, as in XED; the byte form is W0. */ - {const uint8_t w66[]={0x62,0xec,0xfd,8,0x8b,0x11}; - ok&=ck(h,w66,sizeof(w66),"movrs","r18, qword ptr [r17]",X86_REG_R18,8); - const uint8_t w8[]={0x62,0xec,0xfc,8,0x8a,0x11}; - if(cs_disasm(h,w8,sizeof(w8),0,1,&i)){ok=false;cs_free(i,1);}} - {uint8_t x[]={0x62,0xec,0x7c,8,0x8b,0xd1};if(cs_disasm(h,x,6,0,1,&i)){ok=false;cs_free(i,1);}x[2]=0x78;if(cs_disasm(h,x,6,0,1,&i)){ok=false;cs_free(i,1);}x[5]=0x11;x[3]=9;if(cs_disasm(h,x,6,0,1,&i)){ok=false;cs_free(i,1);}x[3]=8;x[2]=0x7e;if(cs_disasm(h,x,6,0,1,&i)){ok=false;cs_free(i,1);}} - cs_close(&h);return ok?0:1; +int main(void) { + csh h; + cs_insn *i = NULL; + bool ok = true; + const uint8_t b8[] = {0x64, 0x62, 0xec, 0x7c, 8, 0x8a, 0x11}; + const uint8_t b16[] = {0x62, 0xec, 0x7d, 8, 0x8b, 0x11}; + const uint8_t b32[] = {0x67, 0x62, 0xec, 0x7c, 8, 0x8b, 0x11}; + const uint8_t b64[] = {0x64, 0x67, 0x62, 0xec, 0xfc, 8, 0x8b, 0x11}; + const uint8_t x4[] = {0x64, 0x62, 0x0c, 0x78, 8, 0x8b, 0x54, 0xa5, 0x20}; + const uint8_t x4a32[] = {0x67, 0x64, 0x62, 0x0c, 0x78, + 8, 0x8b, 0x54, 0xa5, 0x20}; + if (cs_open(CS_ARCH_X86, CS_MODE_64, &h)) + return 1; + cs_option(h, CS_OPT_DETAIL, CS_OPT_ON); + ok &= ck(h, b8, sizeof(b8), "movrs", "r18b, byte ptr fs:[r17]", X86_REG_R18B, + 1); + ok &= + ck(h, b16, sizeof(b16), "movrs", "r18w, word ptr [r17]", X86_REG_R18W, 2); + ok &= ck(h, b32, sizeof(b32), "movrs", "r18d, dword ptr [r17d]", X86_REG_R18D, + 4); + ok &= ck(h, b64, sizeof(b64), "movrs", "r18, qword ptr fs:[r17d]", + X86_REG_R18, 8); + ok &= ck(h, x4, sizeof(x4), "movrs", + "r26d, dword ptr fs:[r29 + r28*4 + 0x20]", X86_REG_R26D, 4); + ok &= ck(h, x4a32, sizeof(x4a32), "movrs", + "r26d, dword ptr fs:[r29d + r28d*4 + 0x20]", X86_REG_R26D, 4); + cs_option(h, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); + ok &= ck(h, b64, sizeof(b64), "movrsq", "%fs:(%r17d), %r18", X86_REG_R18, 8); + cs_option(h, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL); + /* W selects 64-bit operands over 66, as in XED; the byte form is W0. */ + { + const uint8_t w66[] = {0x62, 0xec, 0xfd, 8, 0x8b, 0x11}; + ok &= ck(h, w66, sizeof(w66), "movrs", "r18, qword ptr [r17]", X86_REG_R18, + 8); + const uint8_t w8[] = {0x62, 0xec, 0xfc, 8, 0x8a, 0x11}; + if (cs_disasm(h, w8, sizeof(w8), 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + } + { + uint8_t x[] = {0x62, 0xec, 0x7c, 8, 0x8b, 0xd1}; + if (cs_disasm(h, x, 6, 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + x[2] = 0x78; + if (cs_disasm(h, x, 6, 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + x[5] = 0x11; + x[3] = 9; + if (cs_disasm(h, x, 6, 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + x[3] = 8; + x[2] = 0x7e; + if (cs_disasm(h, x, 6, 0, 1, &i)) { + ok = false; + cs_free(i, 1); + } + } + cs_close(&h); + return ok ? 0 : 1; } diff --git a/tests/unit/x86_apx_setcc.c b/tests/unit/x86_apx_setcc.c index 94644cbda3..f415cd8d89 100644 --- a/tests/unit/x86_apx_setcc.c +++ b/tests/unit/x86_apx_setcc.c @@ -63,7 +63,7 @@ static void encode_register(uint8_t code[6], unsigned int cc, bool zu, code[5] = 0xc0 | (number & 7); } -static bool has_register(const cs_regs registers, uint8_t count, x86_reg reg) +static bool has_register(const uint16_t *registers, uint8_t count, x86_reg reg) { uint8_t i; diff --git a/tests/unit/x86_evex_normalization_boundary.c b/tests/unit/x86_evex_normalization_boundary.c index 860c004ffe..ac1608374d 100644 --- a/tests/unit/x86_evex_normalization_boundary.c +++ b/tests/unit/x86_evex_normalization_boundary.c @@ -266,16 +266,16 @@ static bool check_scalar_compare_llig(csh handle) 0xc2, 0xcb, 0x00 }; - char name[64]; + char case_name[sizeof(name)]; - snprintf(name, sizeof(name), "%s-ll%zu", + snprintf(case_name, sizeof(case_name), "%s-ll%zu", packed_families[family].name, length); if (length == 3) - ok &= check_rejected(handle, name, code, + ok &= check_rejected(handle, case_name, code, sizeof(code)); else ok &= check_packed_compare_length( - handle, name, code, sizeof(code), + handle, case_name, code, sizeof(code), packed_left[length], packed_right[length], false); } diff --git a/tests/unit/x86_vex_legacy_prefix.c b/tests/unit/x86_vex_legacy_prefix.c index 3bb5b9bafd..9372900da6 100644 --- a/tests/unit/x86_vex_legacy_prefix.c +++ b/tests/unit/x86_vex_legacy_prefix.c @@ -21,7 +21,7 @@ static bool check_case(const prefix_case *test) cs_insn *insn = NULL; csh handle; size_t count; - char actual[160] = ""; + char actual[sizeof(insn->mnemonic) + sizeof(insn->op_str)] = ""; bool ok; if (cs_open(CS_ARCH_X86, test->mode, &handle) != CS_ERR_OK)