if ~ defined AVX2 restore AVX2 ; this ensures that symbol cannot be forward-referenced AVX2 = 1 include 'avx.inc' iterate context, @dest,@src,@src2,@aux namespace context define visize calminstruction AVX.parse_vsib_operand#context operand local i, pre, suf compute segment_prefix, 0 compute size, 0 compute displacement_size, 0 transform operand match pre suf, operand jno no_size_prefix transform pre, x86 jno no_size_prefix match :size, pre jno no_size_prefix arrange operand, suf no_size_prefix: match [address], operand jyes memory_operand match =ptr? address, operand jyes memory_operand jump invalid_operand memory_operand: compute type, 'mem' match segment:address, address jno segment_prefix_ok check segment eq 1 elementof segment & 1 metadataof segment relativeto x86.sreg jno invalid_operand compute segment, 1 metadataof segment - x86.sreg check segment >= 4 jyes segment_prefix_386 compute segment_prefix, 26h + segment shl 3 jump segment_prefix_ok segment_prefix_386: compute segment_prefix, 64h + segment-4 segment_prefix_ok: match pre suf, address jno no_address_size_prefix transform pre, x86 jno no_address_size_prefix match :pre, pre jno no_address_size_prefix arrange address, suf check pre = 4 | pre = 8 jno invalid_address_size compute mode, pre shl 3 no_address_size_prefix: compute mode, 0 compute scale, 0 compute index, 0 compute base, 0 compute auto_relative, 0 check size jyes size_override compute size, sizeof address size_override: compute address, address compute base_registers, 0 compute index_registers, 0 compute i, 1 extract_registers: check i > elementsof address jyes registers_extracted check i metadataof address relativeto SSE.reg | i metadataof address relativeto AVX.reg jyes index_term check i metadataof address relativeto x86.r32 | i metadataof address relativeto x86.r64 jno next_term compute base_registers, base_registers + i elementof address * i scaleof address jump next_term index_term: compute index_registers, index_registers + i elementof address * i scaleof address next_term: compute i, i+1 jump extract_registers registers_extracted: compute displacement, address - base_registers - index_registers compute auto_relative, 0 check elementsof index_registers = 1 jno invalid_address compute scale, 1 scaleof index_registers compute index, 0 scaleof (1 metadataof index_registers) check scale and (scale-1) | scale > 8 jyes invalid_address check 1 metadataof index_registers relativeto SSE.reg jyes xmm_index compute visize, 32 jump index_ok xmm_index: compute visize, 16 index_ok: compute rm, 4 check elementsof base_registers = 1 & 1 scaleof base_registers = 1 jyes base_and_index check elementsof base_registers = 0 jno invalid_address compute base, 5 compute displacement_size, 4 compute mod, 0 compute mode, x86.mode check mode > 16 jyes ready compute mode, 32 jump ready base_and_index: compute base, 0 scaleof (1 metadataof base_registers) check mode & mode <> 0 scaleof (1 metadataof (1 metadataof base_registers)) shl 3 jyes invalid_address compute mode, 0 scaleof (1 metadataof (1 metadataof base_registers)) shl 3 setup_displacement: check displacement relativeto 0 jno displacement_32bit check displacement = 0 & rm and 111b <> 5 & (rm <> 4 | base and 111b <> 5) jyes displacement_empty check displacement < 80h & displacement >= -80h jyes displacement_8bit check displacement - 1 shl mode >= -80h & displacement < 1 shl mode jyes displacement_8bit_wrap displacement_32bit: compute displacement_size, 4 compute mod, 2 jump ready displacement_8bit_wrap: compute displacement, displacement - 1 shl mode displacement_8bit: compute displacement_size, 1 compute mod, 1 jump ready index_only: compute displacement_size, 4 compute mod, 0 jump ready displacement_empty: compute displacement_size, 0 compute mod, 0 ready: exit invalid_operand: err 'invalid operand' exit invalid_address: err 'invalid address' exit invalid_address_size: err 'invalid address size' exit end calminstruction end namespace end iterate iterate , vpgatherdd,90h,4, vpgatherqd,91h,8, vgatherdps,92h,4, vgatherqps,93h,8 macro instr? dest*,src*,mask* AVX.parse_operand@dest dest AVX.parse_vsib_operand@src src AVX.parse_operand@aux mask if @dest.type = 'mmreg' & @src.type = 'mem' & @aux.type = 'mmreg' if @src.size and not 4 | (@dest.size > 16 & @dest.size * (asize shr 2) > @src.visize) | (@src.visize > 16 & @dest.size * (asize shr 2) < @src.visize) err 'invalid operand size' else if @aux.size <> @dest.size err 'operand sizes do not match' else if @dest.rm = @aux.rm | @dest.rm = @src.index | @aux.rm = @src.index err 'disallowed combination of registers' end if AVX.store_instruction@src @src.visize,VEX_66_0F38_W0,opcode,@dest.rm,@aux.rm else err 'invalid combination of operands' end if end macro end iterate iterate , vpgatherdq,90h,4, vpgatherqq,91h,8, vgatherdpd,92h,4, vgatherqpd,93h,8 macro instr? dest*,src*,mask* AVX.parse_operand@dest dest AVX.parse_vsib_operand@src src AVX.parse_operand@aux mask if @dest.type = 'mmreg' & @src.type = 'mem' & @aux.type = 'mmreg' if @src.size and not 8 | (@dest.size > 16 & @dest.size * (asize shr 2) > @src.visize * 2) | (@src.visize > 16 & @dest.size * (asize shr 2) < @src.visize * 2) err 'invalid operand size' else if @aux.size <> @dest.size err 'operand sizes do not match' else if @dest.rm = @aux.rm | @dest.rm = @src.index | @aux.rm = @src.index err 'disallowed combination of registers' end if AVX.store_instruction@src @dest.size,VEX_66_0F38_W1,opcode,@dest.rm,@aux.rm else err 'invalid combination of operands' end if end macro end iterate iterate , packsswb,63h, packuswb,67h, packssdw,6Bh, paddb,0FCh, paddw,0FDh, paddd,0FEh, paddq,0D4h, paddsb,0ECh, paddsw,0EDh, paddusb,0DCh, paddusw,0DDh, \ pand,0DBh, pandn,0DFh, pavgb,0E0h, pavgw,0E3h, pcmpeqb,74h, pcmpeqw,75h, pcmpeqd,76h, pcmpgtb,64h, pcmpgtw,65h, pcmpgtd,66h, \ pmaddwd,0F5h, pmaxsw,0EEh, pmaxub,0DEh, pminsw,0EAh, pminub,0DAh, pmulhuw,0E4h, pmulhw,0E5h, pmullw,0D5h, pmuludq,0F4h, \ por,0EBh, psadbw,0F6h, psubb,0F8h, psubw,0F9h, psubd,0FAh, psubq,0FBh, psubsb,0E8h, psubsw,0E9h, psubusb,0D8h, psubusw,0D9h, \ punpckhbw,68h, punpckhwd,69h, punpckhdq,6Ah, punpckhqdq,6Dh, punpcklbw,60h, punpcklwd,61h, punpckldq,62h, punpcklqdq,6Ch, pxor,0EFh macro v#instr? dest*,src*,src2* AVX.basic_instruction VEX_66_0F_W0,opcode,0,dest,src,src2 end macro end iterate iterate , packusdw,2Bh, pcmpeqq,29h, pcmpgtq,37h, phaddw,1, phaddd,2, phaddsw,3, phsubw,5, phsubd,6, phsubsw,7, pmaddubsw,4, \ pmaxsb,3Ch, pmaxsd,3Dh, pmaxuw,3Eh, pmaxud,3Fh, pminsb,38h, pminsd,39h, pminuw,3Ah, pminud,3Bh, pmulhrsw,0Bh, pmulld,40h, pmuldq,28h, \ pshufb,0, psignb,8, psignw,9, psignd,0Ah macro v#instr? dest*,src*,src2* AVX.basic_instruction VEX_66_0F38_W0,opcode,0,dest,src,src2 end macro end iterate iterate , mpsadbw,42h, palignr,0Fh, pblendd,02h macro v#instr? dest*,src*,src2*,imm* AVX.basic_instruction_imm8 VEX_66_0F3A_W0,opcode,0,dest,src,src2,imm end macro end iterate iterate , pabsb,1Ch, pabsw,1Dh, pabsd,1Eh, pblendw,0Eh macro v#instr? dest*,src* AVX.single_source_instruction VEX_66_0F38_W0,opcode,0,dest,src end macro end iterate iterate , pshufd,VEX_66_0F_W0, pshufhw,VEX_F3_0F_W0, pshuflw,VEX_F2_0F_W0 macro v#instr? dest*,src*,imm* AVX.single_source_instruction_imm8 vex_mpw,70h,0,dest,src,imm end macro end iterate iterate , vpsllvd,VEX_66_0F38_W0,47h, vpsllvq,VEX_66_0F38_W1,47h, vpsrlvd,VEX_66_0F38_W0,45h, vpsrlvq,VEX_66_0F38_W1,45h, vpsravd,VEX_66_0F38_W0,46h macro instr? dest*,src*,src2* AVX.basic_instruction vex_mpw,opcode,0,dest,src,src2 end macro end iterate macro vpblendvb? dest*,src*,src2*,mask* AVX.parse_operand@dest dest AVX.parse_operand@src src AVX.parse_operand@src2 src2 AVX.parse_operand@aux mask if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'mmreg' if @src.size <> @dest.size | @src2.size and not @dest.size | @aux.size <> @dest.size err 'operand sizes do not match' end if AVX.store_instruction@src2 @dest.size,VEX_66_0F3A_W0,4Ch,@dest.rm,@src.rm,1,(@aux.rm and 1111b) shl 4 else err 'invalid combination of operands' end if end macro macro vpmovmskb? dest*,src* x86.parse_operand@dest dest AVX.parse_operand@src src if @dest.type = 'reg' & @src.type = 'mmreg' if (@dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8)) err 'invalid operand size' end if AVX.store_instruction@src @src.size,VEX_66_0F_W0,0D7h,@dest.rm else err 'invalid combination of operands' end if end macro iterate , pmovsxbw,20h,8, pmovsxbd,21h,4, pmovsxbq,22h,2, pmovsxwd,23h,8, pmovsxwq,24h,4, pmovsxdq,25h,8, \ pmovzxbw,30h,8, pmovzxbd,31h,4, pmovzxbq,32h,2, pmovzxwd,33h,8, pmovzxwq,34h,4, pmovzxdq,35h,8 macro v#instr? dest*,src* AVX.parse_operand@dest dest AVX.parse_operand@src src if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') if (@src.type = 'mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not (msize * (@dest.size shr 4))) err 'invalid operand size' end if AVX.store_instruction@src @dest.size,VEX_66_0F38_W0,opcode,@dest.rm else err 'invalid combination of operands' end if end macro end iterate iterate , pslldq,7, psrldq,3 macro v#instr dest*,src*,src2* AVX.parse_operand@dest dest AVX.parse_operand@src src x86.parse_operand@src2 src2 if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'imm' if @src2.size and not 1 err 'invalid operand size' else if @src.size <> @dest.size err 'operand sizes do not match' end if AVX.store_instruction@src @dest.size,VEX_66_0F_W0,73h,postbyte,@dest.rm,1,@src2.imm else err 'invalid combination of operands' end if end macro end iterate iterate , psllw,0F1h,71h,6, pslld,0F2h,72h,6, psllq,0F3h,73h,6, psraw,0E1h,71h,4, psrad,0E2h,72h,4, psrlw,0D1h,71h,2, psrld,0D2h,72h,2, psrlq,0D3h,73h,2 macro v#instr? dest*,src*,src2* AVX.parse_operand@dest dest AVX.parse_operand@src src AVX.parse_operand@src2 src2 if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') if @src2.size and not 16 err 'invalid operand size' else if @src.size <> @dest.size err 'operand sizes do not match' end if AVX.store_instruction@src2 @dest.size,VEX_66_0F_W0,opcode_rrm,@dest.rm,@src.rm else if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'imm' if @src2.size and not 1 err 'invalid operand size' else if @src.size <> @dest.size err 'operand sizes do not match' end if AVX.store_instruction@src @dest.size,VEX_66_0F_W0,opcode,postbyte,@dest.rm,1,@src2.imm else err 'invalid combination of operands' end if end macro end iterate macro vmovntdqa? dest*,src* AVX.parse_operand@dest dest x86.parse_operand@src src if @dest.type = 'mmreg' & @src.type = 'mem' if @src.size and not @dest.size err 'operand sizes do not match' end if AVX.store_instruction@src @dest.size,VEX_66_0F38_W0,2Ah,@dest.rm else err 'invalid combination of operands' end if end macro iterate , vpmaskmovd,0, vpmaskmovq,1 macro instr? dest*,src*,src2* AVX.parse_operand@dest dest AVX.parse_operand@src src AVX.parse_operand@src2 src2 if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'mem' if @src.size <> @dest.size | @src2.size and not @dest.size err 'operand sizes do not match' end if AVX.store_instruction@src2 @dest.size,VEX_66_0F38_W#w,8Ch,@dest.rm,@src.rm else if @dest.type = 'mem' & @src.type = 'mmreg' & @src2.type = 'mmreg' if @src.size <> @src2.size | @dest.size and not @src.size err 'operand sizes do not match' end if AVX.store_instruction@dest @src.size,VEX_66_0F38_W#w,8Eh,@src2.rm,@src.rm else err 'invalid combination of operands' end if end macro end iterate macro vbroadcasti128? dest*,src* AVX.parse_operand@dest dest AVX.parse_operand@src src if @dest.type = 'mmreg' & @src.type = 'mem' if @dest.size <> 32 | @src.size and not 16 err 'invalid operand size' end if AVX.store_instruction@src 32,VEX_66_0F38_W0,5Ah,@dest.rm else err 'invalid combination of operands' end if end macro macro vextracti128? dest*,src*,aux* AVX.parse_operand@dest dest AVX.parse_operand@src src x86.parse_operand@aux aux if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm' if @dest.size and not 16 | @src.size <> 32 | @aux.size and not 1 err 'invalid operand size' end if AVX.store_instruction@dest 32,VEX_66_0F3A_W0,39h,@src.rm,,1,@aux.imm else err 'invalid combination of operands' end if end macro macro vinserti128? dest*,src*,src2*,aux* AVX.parse_operand@dest dest AVX.parse_operand@src src AVX.parse_operand@src2 src2 x86.parse_operand@aux aux if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mmreg' | @src2.type = 'mem') & @aux.type = 'imm' if @dest.size <> 32 | @src.size <> 32 | @src2.size and not 16 | @aux.size and not 1 err 'invalid operand size' end if AVX.store_instruction@src2 32,VEX_66_0F3A_W0,38h,@dest.rm,@src.rm,1,@aux.imm else err 'invalid combination of operands' end if end macro macro vperm2i128? dest*,src*,src2*,imm* AVX.basic_instruction_imm8 VEX_66_0F3A_W0,46h,32,dest,src,src2,imm end macro iterate , vbroadcastss,18h,4, vpbroadcastb,78h,1, vpbroadcastw,79h,2, vpbroadcastd,58h,4, vpbroadcastq,59h,8 macro instr? dest*,src* AVX.parse_operand@dest dest AVX.parse_operand@src src if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') if (@src.type='mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not msize) err 'invalid operand size' end if AVX.store_instruction@src @dest.size,VEX_66_0F38_W0,opcode,@dest.rm else err 'invalid combination of operands' end if end macro end iterate macro vbroadcastsd? dest*,src* AVX.parse_operand@dest dest AVX.parse_operand@src src if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') if @dest.size <> 32 | (@src.type='mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not 8) err 'invalid operand size' end if AVX.store_instruction@src 32,VEX_66_0F38_W0,19h,@dest.rm else err 'invalid combination of operands' end if end macro iterate , vpermq,0, vpermpd,1 macro instr? dest*,src*,imm* AVX.single_source_instruction_imm8 VEX_66_0F3A_W1,opcode,32,dest,src,imm end macro end iterate iterate , vpermd,36h, vpermps,16h macro instr? dest*,src*,src2* AVX.basic_instruction VEX_66_0F38_W0,opcode,32,dest,src,src2 end macro end iterate end if