
if ~ defined AVX_512

	restore AVX_512 ; this ensures that symbol cannot be forward-referenced
	AVX_512 = 1

	include 'avx2.inc'

	element AVX_512.reg

	element AVX_512.r128 : AVX_512.reg + 16
	element AVX_512.r256 : AVX_512.reg + 32
	element AVX_512.r512 : AVX_512.reg + 64

	repeat 8, i:0
		element zmm#i? : AVX_512.r512 + i
	end repeat

	if defined xmm8
		repeat 16, i:16
			element xmm#i? : AVX_512.r128 + i
			element ymm#i? : AVX_512.r256 + i
		end repeat
		repeat 8+16, i:8
			element zmm#i? : AVX_512.r512 + i
		end repeat
	end if

	element AVX_512.maskreg

	repeat 8, i:0
		element k#i? : AVX_512.maskreg + i
	end repeat

	define x86.dqqword? :64
	define x86.zword? :64

	EVEX_AS_VEX = 0
	EVEX_W1 = 1 shl 15
	EVEX_REQUIRED = 1 shl 10
	EVEX_FORBIDDEN = 1 shl 2
	EVEX_VL = 1 shl 22

	AVX512VL = 0

	iterate context, @dest,@src,@src2,@aux

		namespace context

			define mask
			define evex_b
			define memsize
			define broadcast
			define rounding
			define visize

			calminstruction AVX_512.parse_operand#context operand

				call	x86.parse_operand#context, operand

				check	type = 'reg' & size = 1 & rm >= 4 & (~ defined x86.REX_FORBIDDEN | rm and x86.REX_FORBIDDEN)
				jyes	invalid_operand
				check	type = 'imm' & size = 0
				jno	export_common

				check	imm eq 1 elementof imm & 1 metadataof imm relativeto SSE.reg
				jyes	xmm_register
				check	imm eq 1 elementof imm & 1 metadataof imm relativeto AVX.reg
				jyes	ymm_register
				check	1 metadataof (1 metadataof imm) relativeto AVX_512.reg & imm eq 1 elementof imm
				jyes	xyzmm_register
				check	imm eq 1 elementof imm & 1 metadataof imm relativeto AVX_512.maskreg
				jyes	mask_register
				exit

			    invalid_operand:
				err	'invalid operand'

			    xmm_register:

				compute rm, 1 metadataof imm - SSE.reg
				compute size, 16

				jump	export_mmreg

			    ymm_register:

				compute rm, 1 metadataof imm - AVX.reg
				compute size, 32

				jump	export_mmreg

			    mask_register:

				compute rm, 1 metadataof imm - AVX_512.maskreg
				compute size, 8
				compute type, 'maskreg'

				jump	export_reg

			    xyzmm_register:

				compute rm, 1 metadataof imm - 1 elementof (1 metadataof imm)
				compute size, 1 metadataof (1 metadataof imm) - AVX_512.reg

			    export_mmreg:

				compute type, 'mmreg'

			    export_reg:

				compute mod, 11b

			    export_common:

				compute mask, 0
				compute evex_b, 0
				compute memsize, 0

			end calminstruction

			calminstruction AVX_512.parse_k1z_operand#context operand

				local	k1, z
				transform operand
				match	operand {k1} { =z? }, operand
				jyes	k1z
				match	operand {k1}, operand
				jyes	k1
				call	AVX_512.parse_operand#context, operand
				exit
			    k1z:
				compute z, 80h
				jump	masked
			    k1:
				compute z, 0
			    masked:
				call	AVX_512.parse_operand#context, operand
				check	z & type = 'mem'
				jyes	invalid_mask
				check	k1 eq 1 elementof k1 & 1 metadataof k1 relativeto AVX_512.maskreg & 1 metadataof k1 - AVX_512.maskreg > 0
				jno	invalid_mask
				compute mask, (1 metadataof k1 - AVX_512.maskreg) or z
				exit
			    invalid_mask:
				err	'invalid mask'

			end calminstruction

			calminstruction AVX_512.parse_k1_operand#context operand

				local	k1
				transform operand
				match	operand {k1}, operand
				jyes	k1
				call	AVX_512.parse_operand#context, operand
				exit
			    k1:
				call	AVX_512.parse_operand#context, operand
				check	k1 eq 1 elementof k1 & 1 metadataof k1 relativeto AVX_512.maskreg & 1 metadataof k1 - AVX_512.maskreg > 0
				jno	invalid_mask
				compute mask, 1 metadataof k1 - AVX_512.maskreg
				exit
			    invalid_mask:
				err	'invalid mask'

			end calminstruction

			calminstruction AVX_512.parse_bcst_operand#context operand,unit

				transform operand
				match	operand {broadcast}, operand
				jyes	mem_bcst
				call	AVX_512.parse_operand#context, operand
				exit

			    invalid_operand:
				err	'invalid operand'

			    mem_bcst:
				call	AVX_512.parse_operand#context, operand

				check	type = 'mem'
				jno	invalid_operand

				compute memsize, unit
				check	memsize
				jyes	implied_unit
				check	size
				jno	operand_size_not_specified
				compute memsize, size
				jump	unit_ok
			    operand_size_not_specified:
				err	'operand size not specified'
				exit
			    implied_unit:
				check	size and not memsize
				jno	unit_ok
				err	'invalid operand size'
				exit
			    unit_ok:

				match	=1to2?, broadcast
				jyes	bcst_2
				match	=1to4?, broadcast
				jyes	bcst_4
				match	=1to8?, broadcast
				jyes	bcst_8
				match	=1to16?, broadcast
				jyes	bcst_16
				err	'invalid broadcast'
				exit
			    bcst_2:
				compute broadcast, 2
				jump	bcst_ok
			    bcst_4:
				compute broadcast, 4
				jump	bcst_ok
			    bcst_8:
				compute broadcast, 8
				jump	bcst_ok
			    bcst_16:
				compute broadcast, 16
			    bcst_ok:
				compute size, memsize * broadcast
				compute evex_b, 1

			end calminstruction

			calminstruction AVX_512.parse_er#context operand,vsize:64

				check	type = 'mem' | size <> vsize
				jyes	invalid_operand

				match	{ =rn?-=sae? }, operand
				jyes	rounding_0
				match	{ =rd?-=sae? }, operand
				jyes	rounding_1
				match	{ =ru?-=sae? }, operand
				jyes	rounding_2
				match	{ =rz?-=sae? }, operand
				jyes	rounding_3
			    invalid_operand:
				err	'invalid operand'
				exit
			    rounding_0:
				compute rounding, 0
				jump	rounding_ok
			    rounding_1:
				compute rounding, 1
				jump	rounding_ok
			    rounding_2:
				compute rounding, 2
				jump	rounding_ok
			    rounding_3:
				compute rounding, 3
				jump	rounding_ok

			    rounding_ok:
				compute evex_b, 1

			end calminstruction

			calminstruction AVX_512.parse_sae#context operand

				check	type = 'mem'
				jyes	invalid_operand

				match	{ =sae? }, operand
				jno	invalid_operand

				compute evex_b, 1
				compute rounding, -1

				exit

			    invalid_operand:
				err	'invalid operand'

			end calminstruction

			calminstruction AVX_512.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 | 1 metadataof (i metadataof address) relativeto AVX_512.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
				check	1 metadataof index_registers relativeto AVX.reg
				jyes	ymm_index
				compute visize, 1 metadataof (1 metadataof index_registers) - AVX_512.reg
				jump	index_ok
			      ymm_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:

				compute mask, 0
				compute evex_b, 0
				compute memsize, 0

				exit

			  invalid_operand:
				err	'invalid operand'
				exit
			  invalid_address:
				err	'invalid address'
				exit
			  invalid_address_size:
				err	'invalid address size'
				exit

			end calminstruction

			calminstruction AVX_512.parse_k1_vsib_operand#context operand

				local	k1
				transform operand
				match	operand {k1}, operand
				jyes	k1
				call	AVX_512.parse_vsib_operand#context, operand
				exit
			    k1:
				call	AVX_512.parse_vsib_operand#context, operand
				check	k1 eq 1 elementof k1 & 1 metadataof k1 relativeto AVX_512.maskreg & 1 metadataof k1 - AVX_512.maskreg > 0
				jno	invalid_mask
				compute mask, 1 metadataof k1 - AVX_512.maskreg
				exit
			    invalid_mask:
				err	'invalid mask'

			end calminstruction

			calminstruction AVX_512.store_instruction#context vsize*,vex_mpw*,evex_f*,opcode*,mask*,reg*,vreg:0,imm_size:0,immediate

				check	segment_prefix
				jno	segment_prefix_ok

				check	mode = 64
				jyes	segment_in_long_mode
				check	mode = 16 & ( rm = 2 | rm = 3 | ( mod > 0 & rm = 6 ) )
				jyes	ss_segment_default
				check	mode = 32 & ( ( mod > 0 & rm = 5 ) | ( rm = 4 & base = 4 ) | ( mod > 0 & rm = 4 & base = 5 ) )
				jyes	ss_segment_default

			    ds_segment_default:
				check	segment_prefix = 3Eh
				jyes	segment_prefix_ok
				jump	store_segment_prefix
			    ss_segment_default:
				check	segment_prefix = 36h
				jyes	segment_prefix_ok
				jump	store_segment_prefix
			    segment_in_long_mode:
				check	segment_prefix < 64h
				jyes	segment_prefix_ok
			    store_segment_prefix:
				emit	1, segment_prefix
			    segment_prefix_ok:

				check	mod <> 11b & mode <> x86.mode
				jno	addressing_prefix_ok
				check	mode = 64 | (mode = 16 & x86.mode = 64)
				jno	store_addressing_prefix
				err	'illegal addressing mode'
			    store_addressing_prefix:
				emit	1, 67h
			    addressing_prefix_ok:

				compute evex, vex_mpw
				compute evex_flags, evex_f

				check	evex_b
				jno	evex_L'L
				compute evex, evex or evex_b shl 20
			    evex_L'L:
				check	mod = 11b & evex_b & rounding >= 0
				jyes	evex_rounding
				check	vsize = 64
				jyes	evex_L'
				check	evex_flags and EVEX_VL & AVX512VL = 0
				jno	evex_L
				compute evex_flags, evex_flags or EVEX_FORBIDDEN
			    evex_L:
				check	vsize = 32
				jno	evex_mask
				compute evex, evex or 1 shl 21
				jump	evex_mask
			    evex_L':
				compute evex, evex or 1 shl 22
				jump	evex_mask
			    evex_rounding:
				compute evex, evex or rounding shl 21

			    evex_mask:
				check	mask
				jno	evex_X
				compute evex, evex or mask shl 16

			    evex_X:
				check	rm and 10000b | (mod <> 11b & mode > 16 & rm = 4 & index and 1000b)
				jno	evex_B
				compute evex, evex or 1 shl 6
			    evex_B:
				check	rm and 1000b | (mod <> 11b & mode > 16 & rm = 4 & base and 1000b)
				jno	evex_R'
				compute evex, evex or 1 shl 5
			    evex_R':
				check	reg and 10000b
				jno	evex_R
				compute evex, evex or 1 shl 4
			    evex_R:
				check	reg and 1000b
				jno	evex_V'
				compute evex, evex or 1 shl 7
			    evex_V':
				check	vreg and 10000b
				jno	evex_vvvv
				compute evex, evex or 1 shl 19
			    evex_vvvv:
				compute evex, evex or (vreg and 1111b) shl 11

				check	x86.mode < 64 & evex and 00001000_01000000_11110000b
				jno	allowed
				err	'instruction requires long mode'
			    allowed:

				local	evex_displacement_size, compressed_displacement

				check	displacement_size
				jno	no_displacement_compression
				compute displacement, displacement
				check	(mode > 16 & rm = 5) | (mode = 16 & rm = 6)
				jyes	no_displacement_compression
				check	memsize
				jyes	displacement_compression
				compute memsize, vsize
			    displacement_compression:
				check	displacement relativeto 0 & displacement mod? memsize = 0
				jno	displacement_incompressible
				compute compressed_displacement, displacement / memsize
				check	compressed_displacement < 80h & compressed_displacement >= -80h
				jyes	displacement_compressed
				check	compressed_displacement - 1 shl mode >= -80h & compressed_displacement < 1 shl mode
				jno	displacement_incompressible
				compute compressed_displacement, compressed_displacement - 1 shl mode
			    displacement_compressed:
				compute evex_displacement_size, 1
				jump	choose_prefix
			    displacement_incompressible:
				compute evex_displacement_size, 4
				check	mode > 16
				jyes	choose_prefix
				compute evex_displacement_size, 2
				jump	choose_prefix
			    no_displacement_compression:
				compute evex_displacement_size, displacement_size

			    choose_prefix:
				check	evex_flags and EVEX_REQUIRED | evex and 11011111_00000000_00010000b | rm and 10000b
				jyes	evex_required
				check	~ evex_flags and EVEX_FORBIDDEN & evex_displacement_size + 1 < displacement_size
				jyes	evex
				jump	vex
			    evex_required:
				check	evex_flags and EVEX_FORBIDDEN
				jno	evex
				err	'invalid operand'

			    vex:
				compute vex, evex and 11111011_11111111b or (evex and 1 shl 21) shr (21-10)
				check	vex and 10000000_01111111b <> 1
				jyes	vex_3byte
			    vex_2byte:
				emit	1, 0C5h
				emit	1, ((vex and 10000000b) or ((vex shr 8) and 1111111b)) xor 11111000b
				jump	evex_done
			    vex_3byte:
				emit	1, 0C4h
				emit	1, (vex and 11111111b) xor 11100000b
				emit	1, (vex shr 8) xor 01111000b
				jump	evex_done

			    evex:
				compute evex, evex or 1 shl 10
				check	evex_flags and EVEX_W1
				jno	evex_4byte
				compute evex, evex or 1 shl 15
			    evex_4byte:
				emit	4, 62h + (evex xor 00001000_01111000_11110000b) shl 8
				check	mod <> 11b & mod <> 0 & evex_displacement_size > 0
				jno	evex_done
				compute displacement_size, evex_displacement_size
				check	evex_displacement_size = 1
				jyes	evex_compressed_displacement
				compute mod, 2
				jump	evex_done
			    evex_compressed_displacement:
				compute displacement, compressed_displacement
				compute mod, 1
			    evex_done:

				asm	db opcode
				emit	1, mod shl 6 + (reg and 111b) shl 3 + rm and 111b

				check	mod <> 11b & rm = 4 & mode <> 16
				jno	sib_ok
				emit	1, (bsf scale) shl 6 + (index and 111b) shl 3 + base and 111b
			    sib_ok:

				check	displacement_size = 1
				jyes	displacement_8bit
				check	displacement_size = 2
				jyes	displacement_16bit
				check	displacement_size = 4 | displacement_size = 8
				jno	displacement_ok

				check	auto_relative
				jno	auto_relative_ok
				check	imm_size < 8
				jyes	adjust_auto_relative_displacement
				compute displacement, displacement - ($ + 4 + 4)
				jump	auto_relative_ok
			      adjust_auto_relative_displacement:
				compute displacement, displacement - ($ + 4 + imm_size)
			      auto_relative_ok:

				check	mode = 64 & displacement relativeto 0
				jno	displacement_ready
				check	displacement - 1 shl 64 >= -80000000h & displacement < 1 shl 64
				jyes	adjust_displacement_wrap
				check	displacement >= -80000000h & displacement < 80000000h
				jyes	displacement_ready
				err	'address value out of signed range'
			      adjust_displacement_wrap:
				compute displacement, displacement - 1 shl 64
			      displacement_ready:

				asm	dd displacement

				jump	displacement_ok
			    displacement_16bit:
				asm	dw displacement
				jump	displacement_ok
			    displacement_8bit:
				emit	1, displacement
			    displacement_ok:

				check	imm_size = 1
				jyes	immediate_8bit
				check	imm_size = 2
				jyes	immediate_16bit
				check	imm_size = 4
				jyes	immediate_32bit
				check	imm_size = 8
				jno	immediate_ok
				call	x86.simm32, immediate
				jump	immediate_ok
			    immediate_32bit:
				compute imm, +immediate
				asm	dd imm
				jump	immediate_ok
			    immediate_16bit:
				compute imm, +immediate
				asm	dw imm
				jump	immediate_ok
			    immediate_8bit:
				compute imm, +immediate
				emit	1, imm
			    immediate_ok:

			end calminstruction

		end namespace

	end iterate

	macro AVX_512.basic_instruction_bcst_er vex_mpw,evex_f,opcode,unit,dest,src,src_er&
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		match src2=,er, src_er
			AVX_512.parse_operand@src2 src2
			AVX_512.parse_er@src2 er
		else
			AVX_512.parse_bcst_operand@src2 src_er,unit
		end match
		if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
			if @src.size <> @dest.size | @src2.size and not @dest.size
				err 'operand sizes do not match'
			end if
			AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.basic_instruction_bcst_sae vex_mpw,evex_f,opcode,unit,dest,src,src_sae&
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		match src2=,sae, src_sae
			AVX_512.parse_operand@src2 src2
			AVX_512.parse_sae@src2 sae
		else
			AVX_512.parse_bcst_operand@src2 src_sae,unit
		end match
		if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
			if @src.size <> @dest.size | @src2.size and not @dest.size
				err 'operand sizes do not match'
			end if
			AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.basic_instruction_bcst_sae_imm8 vex_mpw,evex_f,opcode,unit,dest,src,src2,aux&
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		AVX_512.parse_bcst_operand@src2 src2,unit
		match sae=,imm, aux
			AVX_512.parse_sae@src2 sae
			x86.parse_operand@aux imm
		else
			x86.parse_operand@aux aux
		end match
		if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm'
			if @src.size <> @dest.size | @src2.size and not @dest.size | @aux.size and not 1
				err 'operand sizes do not match'
			end if
			AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.basic_instruction_bcst vex_mpw,evex_f,opcode,unit,dest,src,src2
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		AVX_512.parse_bcst_operand@src2 src2,unit
		if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
			if @src.size <> @dest.size | @src2.size and not @dest.size
				err 'operand sizes do not match'
			end if
			AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.basic_instruction_bcst_imm8 vex_mpw,evex_f,opcode,unit,dest,src,src2,aux
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		AVX_512.parse_bcst_operand@src2 src2,unit
		x86.parse_operand@aux aux
		if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm'
			if @aux.size and not 1
				err 'invalid operand size'
			else if @src.size <> @dest.size | @src2.size and not @dest.size
				err 'operand sizes do not match'
			end if
			AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.basic_instruction_er vex_mpw,evex_f,opcode,unit,dest,src,src_er&
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		match src2=,er, src_er
			AVX_512.parse_operand@src2 src2
			AVX_512.parse_er@src2 er,(unit-1) and not 15 + 16
		else
			AVX_512.parse_operand@src2 src_er
		end match
		if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
			if unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src2.type = 'mem' & @src2.size and not unit) )
				err 'invalid operand size'
			else if @dest.size <> @src.size | (@src2.size and not @dest.size & (unit = 0 | @src2.type = 'mmreg'))
				err 'operand sizes do not match'
			end if
			@src2.memsize = unit
			AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.basic_instruction_sae vex_mpw,evex_f,opcode,unit,dest,src,src_sae&
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		match src2=,sae, src_sae
			AVX_512.parse_operand@src2 src2
			AVX_512.parse_sae@src2 sae
		else
			AVX_512.parse_operand@src2 src_sae
		end match
		if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
			if unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src2.type = 'mem' & @src2.size and not unit) )
				err 'invalid operand size'
			else if @dest.size <> @src.size | (@src2.size and not @dest.size & (unit = 0 | @src2.type = 'mmreg'))
				err 'operand sizes do not match'
			end if
			@src2.memsize = unit
			AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.basic_instruction_sae_imm8 vex_mpw,evex_f,opcode,unit,dest,src,src2,aux&
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		AVX_512.parse_operand@src2 src2
		match sae=,imm, aux
			AVX_512.parse_sae@src2 sae
			x86.parse_operand@aux imm
		else
			x86.parse_operand@aux aux
		end match
		if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm'
			if ( unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src2.type = 'mem' & @src2.size and not unit) ) ) | @aux.size and not 1
				err 'invalid operand size'
			else if @dest.size <> @src.size | (@src2.size and not @dest.size & (unit = 0 | @src2.type = 'mmreg'))
				err 'operand sizes do not match'
			end if
			@src2.memsize = unit
			AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.basic_instruction vex_mpw,evex_f,opcode,unit,dest,src,src2
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		AVX_512.parse_operand@src2 src2
		if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
			if unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src2.type = 'mem' & @src2.size and not unit) )
				err 'invalid operand size'
			else if @dest.size <> @src.size | (@src2.size and not @dest.size & (unit = 0 | @src2.type = 'mmreg'))
				err 'operand sizes do not match'
			end if
			@src2.memsize = unit
			AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.basic_instruction_imm8 vex_mpw,evex_f,opcode,unit,dest,src,src2,aux&
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		AVX_512.parse_operand@src2 src2
		x86.parse_operand@aux aux
		if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm'
			if ( unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src2.type = 'mem' & @src2.size and not unit) ) ) | @aux.size and not 1
				err 'invalid operand size'
			else if @dest.size <> @src.size | (@src2.size and not @dest.size & (unit = 0 | @src2.type = 'mmreg'))
				err 'operand sizes do not match'
			end if
			@src2.memsize = unit
			AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.single_source_instruction_bcst_er vex_mpw,evex_f,opcode,unit,dest,src_er&
		AVX_512.parse_k1z_operand@dest dest
		match src=,er, src_er
			AVX_512.parse_operand@src src
			AVX_512.parse_er@src er
		else
			AVX_512.parse_bcst_operand@src src_er,unit
		end match
		if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
			if @src.size and not @dest.size
				err 'operand sizes do not match'
			end if
			AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.single_source_instruction_bcst_sae vex_mpw,evex_f,opcode,unit,dest,src_sae&
		AVX_512.parse_k1z_operand@dest dest
		match src=,sae, src_sae
			AVX_512.parse_operand@src src
			AVX_512.parse_sae@src sae
		else
			AVX_512.parse_bcst_operand@src src_sae,unit
		end match
		if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
			if @src.size and not @dest.size
				err 'operand sizes do not match'
			end if
			AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.single_source_instruction_bcst_sae_imm8 vex_mpw,evex_f,opcode,unit,dest,src,aux&
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_bcst_operand@src src,unit
		match sae=,imm, aux
			AVX_512.parse_sae@src sae
			x86.parse_operand@aux imm
		else
			x86.parse_operand@aux aux
		end match
		if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm'
			if @aux.size and not 1
				err 'invalid operand size'
			else if @src.size and not @dest.size
				err 'operand sizes do not match'
			end if
			AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,,1,@aux.imm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.single_source_instruction_bcst vex_mpw,evex_f,opcode,unit,dest,src&
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_bcst_operand@src src,unit
		if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
			if @src.size and not @dest.size
				err 'operand sizes do not match'
			end if
			AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro AVX_512.single_source_instruction vex_mpw,evex_f,opcode,unit,dest,src
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
			if unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src.type = 'mem' & @src.size and not unit) )
				err 'invalid operand size'
			else if @src.size and not @dest.size & (unit = 0 | @src.type = 'mmreg')
				err 'operand sizes do not match'
			end if
			@src.memsize = unit
			AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	iterate <instr,opcode>, add,58h, mul,59h, sub,5Ch, div,5Eh

		macro v#instr#pd? dest*,src*,src2*&
			AVX_512.basic_instruction_bcst_er VEX_66_0F_W0,EVEX_W1+EVEX_VL,opcode,8,dest,src,src2
		end macro

		macro v#instr#ps? dest*,src*,src2*&
			AVX_512.basic_instruction_bcst_er VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src,src2
		end macro

		macro v#instr#sd? dest*,src*,src2*&
			AVX_512.basic_instruction_er VEX_F2_0F_W0,EVEX_W1,opcode,8,dest,src,src2
		end macro

		macro v#instr#ss? dest*,src*,src2*&
			AVX_512.basic_instruction_er VEX_F3_0F_W0,EVEX_AS_VEX,opcode,4,dest,src,src2
		end macro

	end iterate

	iterate <instr,opcode>, min,5Dh, max,5Fh

		macro v#instr#pd? dest*,src*,src2*&
			AVX_512.basic_instruction_bcst_sae VEX_66_0F_W0,EVEX_W1+EVEX_VL,opcode,8,dest,src,src2
		end macro

		macro v#instr#ps? dest*,src*,src2*&
			AVX_512.basic_instruction_bcst_sae VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src,src2
		end macro

		macro v#instr#sd? dest*,src*,src2*&
			AVX_512.basic_instruction_sae VEX_F2_0F_W0,EVEX_W1,opcode,8,dest,src,src2
		end macro

		macro v#instr#ss? dest*,src*,src2*&
			AVX_512.basic_instruction_sae VEX_F3_0F_W0,EVEX_AS_VEX,opcode,4,dest,src,src2
		end macro

	end iterate

	iterate <instr,opcode>, unpckh,15h, unpckl,14h

		macro v#instr#pd? dest*,src*,src2*&
			AVX_512.basic_instruction_bcst VEX_66_0F_W0,EVEX_W1+EVEX_VL,opcode,8,dest,src,src2
		end macro

		macro v#instr#ps? dest*,src*,src2*&
			AVX_512.basic_instruction_bcst VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src,src2
		end macro

	end iterate

	macro vsqrtpd? dest*,src*&
		AVX_512.single_source_instruction_bcst_er VEX_66_0F_W0,EVEX_W1+EVEX_VL,51h,8,dest,src
	end macro

	macro vsqrtps? dest*,src*&
		AVX_512.single_source_instruction_bcst_er VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,51h,4,dest,src
	end macro

	macro vsqrtsd? dest*,src*,src2*&
		AVX_512.basic_instruction_er VEX_F2_0F_W0,EVEX_W1,51h,8,dest,src,src2
	end macro

	macro vsqrtss? dest*,src*,src2*&
		AVX_512.basic_instruction_er VEX_F3_0F_W0,EVEX_AS_VEX,51h,4,dest,src,src2
	end macro

	macro vshufpd? dest*,src*,src2*,aux*&
		AVX_512.basic_instruction_bcst_imm8 VEX_66_0F_W0,EVEX_W1+EVEX_VL,0C6h,8,dest,src,src2,aux
	end macro

	macro vshufps? dest*,src*,src2*,aux*&
		AVX_512.basic_instruction_bcst_imm8 VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,0C6h,4,dest,src,src2,aux
	end macro

	macro vbroadcastss? dest*,src*
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.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 4)
				err 'invalid operand size'
			end if
			@src2.memsize = 4
			AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,18h,@dest.mask,@dest.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro vbroadcastsd? dest*,src*
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem')
			if @dest.size = 16 | (@src.type = 'mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not 8)
				err 'invalid operand size'
			end if
			@src.memsize = 8
			AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_W1+EVEX_VL,19h,@dest.mask,@dest.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	iterate <instr,opcode,opcode_g,msize>, vpbroadcastd,58h,7Ch,4, vpbroadcastq,59h,7Ch,8

		macro instr? dest*,src*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.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
				@src.memsize = msize
				AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX,opcode,@dest.mask,@dest.rm
			else if @dest.type = 'mmreg' & @src.type = 'reg'
				if @src.size <> msize & (@src.size <> 4 | msize = 8)
					err 'invalid operand size'
				end if
				@src.memsize = msize
				if msize = 8
					AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode_g,@dest.mask,@dest.rm
				else
					AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode_g,@dest.mask,@dest.rm
				end if
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,vex_mpw,opcode,msize>, vbroadcastf32x4,VEX_66_0F38_W0,1Ah,16, vbroadcastf64x4,VEX_66_0F38_W1,1Bh,32, \
					      vbroadcasti32x4,VEX_66_0F38_W0,5Ah,16, vbroadcasti64x4,VEX_66_0F38_W1,5Bh,32

		macro instr? dest*,src*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_operand@src src
			if @dest.type = 'mmreg' & @src.type = 'mem'
				if @dest.size <= msize | @src.size and not msize
					err 'invalid operand size'
				end if
				@src.memsize = msize
				AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,vex_mpw,opcode,unit>, vshuff32x4,VEX_66_0F3A_W0,23h,4, vshuff64x2,VEX_66_0F3A_W1,23h,4, \
					     vshufi32x4,VEX_66_0F3A_W0,43h,4, vshufi64x2,VEX_66_0F3A_W1,43h,4

		macro instr? dest*,src*,src2*,aux*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_operand@src src
			AVX_512.parse_bcst_operand@src2 src2,unit
			x86.parse_operand@aux aux
			if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm'
				if @dest.size < 32 | @aux.size and not 1
					err 'invalid operand size'
				else if @src.size <> @dest.size | @src2.size and not @dest.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src2 @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	macro vextractps? dest*,src*,aux*
		AVX_512.parse_operand@dest dest
		AVX_512.parse_operand@src src
		x86.parse_operand@aux aux
		if (@dest.type = 'reg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm'
			if @dest.size and not 4 | @src.size <> 16 | @aux.size and not 1
				err 'invalid operand size'
			end if
			@dest.memsize = 4
			AVX_512.store_instruction@dest 16,VEX_66_0F3A_W0,EVEX_AS_VEX,17h,0,@src.rm,,1,@aux.imm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro vinsertps? dest*,src*,src2*,aux*
		AVX_512.parse_operand@dest dest
		AVX_512.parse_operand@src src
		AVX_512.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 <> 16 | @src.size <> 16 | (@src2.type = 'mmreg' & @src2.size <> 16) | (@src2.type = 'mem' & @src2.size and not 4) | @aux.size and not 1
				err 'invalid operand size'
			end if
			@src2.memsize = 4
			AVX_512.store_instruction@src2 16,VEX_66_0F3A_W0,EVEX_AS_VEX,21h,0,@dest.rm,@src.rm,1,@aux.imm
		else
			err 'invalid combination of operands'
		end if
	end macro

	iterate <instr,vex_mpw,opcode,msize>, vextractf32x4,VEX_66_0F3A_W0,19h,16, vextractf64x4,VEX_66_0F3A_W1,1Bh,32, \
					      vextracti32x4,VEX_66_0F3A_W0,39h,16, vextracti64x4,VEX_66_0F3A_W1,3Bh,32

		macro instr? dest*,src*,aux*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.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 msize | @src.size <= msize | @aux.size and not 1
					err 'invalid operand size'
				end if
				@dest.memsize = msize
				AVX_512.store_instruction@dest @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@src.rm,,1,@aux.imm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,vex_mpw,opcode,msize>, vinsertf32x4,VEX_66_0F3A_W0,18h,16, vinsertf64x4,VEX_66_0F3A_W1,1Ah,32, \
					      vinserti32x4,VEX_66_0F3A_W0,38h,16, vinserti64x4,VEX_66_0F3A_W1,3Ah,32

		macro instr? dest*,src*,src2*,aux*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_operand@src src
			AVX_512.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 <= msize | @src.size <= msize | @src2.size and not msize | @aux.size and not 1
					err 'invalid operand size'
				end if
				@src2.memsize = msize
				AVX_512.store_instruction@src2 @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,vex_mpw,evex_mpw,unit>, vcmpps,VEX_0F_W0,VEX_0F_W0,4, vcmppd,VEX_66_0F_W0,VEX_66_0F_W1,8

		macro instr? dest*,src*,src2*,aux*&
			AVX_512.parse_k1_operand@dest dest
			AVX_512.parse_operand@src src
			AVX_512.parse_bcst_operand@src2 src2,unit
			match sae=,imm, aux
				AVX_512.parse_sae@src2 sae
				x86.parse_operand@aux imm
			else
				x86.parse_operand@aux aux
			end match
			if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm'
				if @aux.size and not 1
					err 'invalid operand size'
				else if @src.size <> @dest.size | @src2.size and not @dest.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src2 @src.size,vex_mpw,EVEX_FORBIDDEN,0C2h,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
			else if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm'
				if @aux.size and not 1
					err 'invalid operand size'
				else if @src2.size and not @src.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src2 @src.size,evex_mpw,EVEX_REQUIRED+EVEX_VL,0C2h,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,vex_mpw,evex_mpw,unit>, vcmpss,VEX_F3_0F_W0,VEX_F3_0F_W0,4, vcmpsd,VEX_F2_0F_W0,VEX_F2_0F_W1,8

		macro instr? dest*,src*,src2*,aux*&
			AVX_512.parse_k1_operand@dest dest
			AVX_512.parse_operand@src src
			AVX_512.parse_operand@src2 src2
			match sae=,imm, aux
				AVX_512.parse_sae@src2 sae
				x86.parse_operand@aux imm
			else
				x86.parse_operand@aux aux
			end match
			if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm'
				if @dest.size <> 16 | (@src2.type = 'mem' & @src2.size and not unit)
					err 'invalid operand size'
				else if @dest.size <> @src.size | (@src2.type = 'mmreg' & @src2.size <> @dest.size)
					err 'operand sizes do not match'
				end if
				@src2.memsize = unit
				AVX_512.store_instruction@src2 @src.size,vex_mpw,EVEX_FORBIDDEN,0C2h,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
			else if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm'
				if @src.size <> 16 | (@src2.type = 'mem' & @src2.size and not unit) | @aux.size and not 1
					err 'invalid operand size'
				else if @src2.type = 'mmreg' & @src2.size <> @src.size
					err 'operand sizes do not match'
				end if
				@src2.memsize = unit
				AVX_512.store_instruction@src2 @src.size,evex_mpw,EVEX_REQUIRED,0C2h,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <cond,code>, eq,0, lt,1, le,2, unord,3, neq,4, nlt,5, nle,6, ord,7, \
			     eq_uq,8, nge,9, ngt,0Ah, false,0Bh, neq_qq,0Ch, ge,0Dh, gt,0Eh, true,0Fh, \
			     eq_os,10h, lt_oq,11h, le_oq,12h, unord_s,13h, neq_us,14h, nlt_uq,15h, nle_uq,16h, ord_s,17h, \
			     eq_us,18h, nge_uq,19h, ngt_uq,1Ah, false_os,1Bh, neq_os,1Ch, ge_oq,1Dh, gt_oq,1Eh, true_us,1Fh

		macro vcmp#cond#pd? dest*,src*,src2*&
			vcmppd dest,src,src2,code
		end macro

		macro vcmp#cond#ps? dest*,src*,src2*&
			vcmpps dest,src,src2,code
		end macro

		macro vcmp#cond#sd? dest*,src*,src2*&
			vcmpsd dest,src,src2,code
		end macro

		macro vcmp#cond#ss? dest*,src*,src2*&
			vcmpss dest,src,src2,code
		end macro

	end iterate

	iterate <instr,vex_mpw,evex_f,opcode,unit>, vcomiss,VEX_0F_W0,EVEX_AS_VEX,2Fh,4, vcomisd,VEX_66_0F_W0,EVEX_W1,2Fh,8, vucomiss,VEX_0F_W0,EVEX_AS_VEX,2Eh,4, vucomisd,VEX_66_0F_W0,EVEX_W1,2Eh,8

		macro instr? dest*,src_sae*&
			AVX_512.parse_k1z_operand@dest dest
			match src=,sae, src_sae
				AVX_512.parse_operand@src src
				AVX_512.parse_sae@src sae
			else
				AVX_512.parse_operand@src src_sae
			end match
			if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
				if unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src.type = 'mem' & @src.size and not unit) )
					err 'invalid operand size'
				else if @src.size and not @dest.size & (unit = 0 | @src.type = 'mmreg')
					err 'operand sizes do not match'
				end if
				@src.memsize = unit
				AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,opcode>, kandw,41h, kandnw,42h, knotw,44h, korw,45h, kxnorw,46h, kxorw,47h

		macro instr? dest*,src*,src2*
			AVX_512.parse_operand@dest dest
			AVX_512.parse_operand@src src
			AVX_512.parse_operand@src2 src2
			if @dest.type = 'maskreg' & @src.type = 'maskreg' & @src2.type = 'maskreg'
				AVX.store_instruction@src2 32,VEX_0F_W0,opcode,@dest.rm,@src.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,opcode>, knotw,44h, kortestw,98h

		macro instr? dest*,src*
			AVX_512.parse_operand@dest dest
			AVX_512.parse_operand@src src
			if @dest.type = 'maskreg' & @src.type = 'maskreg'
				AVX.store_instruction@src 16,VEX_0F_W0,opcode,@dest.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	macro kmovw? dest*,src*
		AVX_512.parse_operand@dest dest
		AVX_512.parse_operand@src src
		if @dest.type = 'maskreg' & (@src.type = 'maskreg' | @src.type = 'mem')
			if @src.type = 'mem' & @src.size and not 2
				err 'invalid operand size'
			end if
			AVX.store_instruction@src 16,VEX_0F_W0,90h,@dest.rm
		else if @dest.type = 'mem' & @src.type = 'maskreg'
			if @dest.size and not 2
				err 'invalid operand size'
			end if
			AVX.store_instruction@dest 16,VEX_0F_W0,91h,@src.rm
		else if @dest.type = 'maskreg' & @src.type = 'reg'
			if @src.size <> 4
				err 'invalid operand size'
			end if
			AVX.store_instruction@src 16,VEX_0F_W0,92h,@dest.rm
		else if @dest.type = 'reg' & @src.type = 'maskreg'
			if @dest.size <> 4
				err 'invalid operand size'
			end if
			AVX.store_instruction@src 16,VEX_0F_W0,93h,@dest.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	iterate <instr,vex_mpw,opcode>, kshiftrw,VEX_66_0F3A_W1,30h, kshiftlw,VEX_66_0F3A_W1,32h

		macro instr? dest*,src*,aux*
			AVX_512.parse_operand@dest dest
			AVX_512.parse_operand@src src
			x86.parse_operand@aux aux
			if @dest.type = 'maskreg' & @src.type = 'maskreg' & @aux.type = 'imm'
				if @aux.size and not 1
					err 'invalid operand size'
				end if
				AVX.store_instruction@src 16,vex_mpw,opcode,@dest.rm,,1,@aux.imm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	macro kunpckbw? dest*,src*,src2*
		AVX_512.parse_operand@dest dest
		AVX_512.parse_operand@src src
		AVX_512.parse_operand@src2 src2
		if @dest.type = 'maskreg' & @src.type = 'maskreg' & @src2.type = 'maskreg'
			AVX.store_instruction@src2 32,VEX_66_0F_W0,4Bh,@dest.rm,@src.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	iterate <instr,evex_f,opcode>, vcvtdq2pd,EVEX_AS_VEX+EVEX_VL,0E6h, vcvtudq2pd,EVEX_REQUIRED+EVEX_VL,7Ah

		macro instr? dest*,src*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_bcst_operand@src src,4
			if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
				if (@src.type = 'mem' & @src.size and not (@dest.size shr 1)) | (@src.type = 'mmreg' & (@dest.size shr 1 - 1) and not 15 + 16 <> @src.size)
					err 'invalid operand size'
				end if
				if @src.memsize = 0
					@src.memsize = @dest.size shr 1
				end if
				AVX_512.store_instruction@src @dest.size,VEX_F3_0F_W0,evex_f,opcode,@dest.mask,@dest.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,vex_mpw,evex_f,opcode>, vcvtpd2dq,VEX_F2_0F_W0,EVEX_W1+EVEX_VL,0E6h, vcvtpd2ps,VEX_66_0F_W0,EVEX_W1+EVEX_VL,5Ah, vcvtpd2udq,VEX_0F_W1,EVEX_REQUIRED+EVEX_VL,79h

		macro instr? dest*,src_er*&
			AVX_512.parse_k1z_operand@dest dest
			match src=,er, src_er
				AVX_512.parse_operand@src src
				AVX_512.parse_er@src er
			else
				AVX_512.parse_bcst_operand@src src_er,8
			end match
			if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
				if @src.size = 0
					if @dest.size = 16
						err 'operand size not specified'
					else
						@src.size = 64
					end if
				end if
				if (@src.size shr 1 - 1) and not 15 + 16 <> @dest.size | @src.size > 64
					err 'invalid operand size'
				end if
				AVX_512.store_instruction@src @src.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,vex_mpw,evex_f,opcode>, vcvtps2pd,VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,5Ah

		macro instr? dest*,src_sae*&
			AVX_512.parse_k1z_operand@dest dest
			match src=,sae, src_sae
				AVX_512.parse_operand@src src
				AVX_512.parse_sae@src sae
			else
				AVX_512.parse_bcst_operand@src src_sae,4
			end match
			if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
				if (@src.type = 'mem' & @src.size and not (@dest.size shr 1)) | (@src.type = 'mmreg' & (@dest.size shr 1 - 1) and not 15 + 16 <> @src.size)
					err 'invalid operand size'
				end if
				if @src.memsize = 0
					@src.memsize = @dest.size shr 1
				end if
				AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,vex_mpw,evex_f,opcode>, vcvttpd2dq,VEX_66_0F_W0,EVEX_W1+EVEX_VL,0E6h, vcvttpd2udq,VEX_0F_W1,EVEX_REQUIRED+EVEX_VL,78h

		macro instr? dest*,src_sae*&
			AVX_512.parse_k1z_operand@dest dest
			match src=,sae, src_sae
				AVX_512.parse_operand@src src
				AVX_512.parse_sae@src sae
			else
				AVX_512.parse_bcst_operand@src src_sae,8
			end match
			if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
				if @src.size = 0
					if @dest.size = 16
						err 'operand size not specified'
					else
						@src.size = 64
					end if
				end if
				if (@src.size shr 1 - 1) and not 15 + 16 <> @dest.size | @src.size > 64
					err 'invalid operand size'
				end if
				AVX_512.store_instruction@src @src.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,vex_mpw,evex_f,opcode>, vcvtdq2ps,VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,5Bh, vcvtudq2ps,VEX_F2_0F_W0,EVEX_REQUIRED+EVEX_VL,7Ah, \
					       vcvtps2dq,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL,5Bh, vcvtps2udq,VEX_0F_W0,EVEX_REQUIRED+EVEX_VL,79h

		macro instr? dest*,src*&
			AVX_512.single_source_instruction_bcst_er vex_mpw,evex_f,opcode,4,dest,src
		end macro

	end iterate


	iterate <instr,vex_mpw,evex_f,opcode>, vcvttps2dq,VEX_F3_0F_W0,EVEX_AS_VEX+EVEX_VL,5Bh, vcvttps2udq,VEX_0F_W0,EVEX_REQUIRED+EVEX_VL,78h

		macro instr? dest*,src*&
			AVX_512.single_source_instruction_bcst_sae vex_mpw,evex_f,opcode,4,dest,src
		end macro

	end iterate

	macro vcvtph2ps? dest*,src_sae*&
		AVX_512.parse_k1z_operand@dest dest
		match src=,sae, src_sae
			AVX_512.parse_operand@src src
			AVX_512.parse_sae@src sae
		else
			AVX_512.parse_operand@src src_sae
		end match
		if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
			if (@src.type = 'mem' & @src.size and not (@dest.size shr 1)) | (@src.type = 'mmreg' & (@dest.size shr 1 - 1) and not 15 + 16 <> @src.size)
				err 'invalid operand size'
			end if
			if @src.memsize = 0
				@src.memsize = @dest.size shr 1
			end if
			AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,13h,@dest.mask,@dest.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro vcvtps2ph? dest*,src*,aux*&
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		match sae=,imm, aux
			AVX_512.parse_sae@dest sae
			x86.parse_operand@aux imm
		else
			x86.parse_operand@aux aux
		end match
		if (@dest.type = 'mem' | @dest.type = 'mmreg') & @src.type = 'mmreg'
			if (@dest.type = 'mem' & @dest.size and not (@src.size shr 1)) | (@dest.type = 'mmreg' & (@src.size shr 1 - 1) and not 15 + 16 <> @dest.size)
				err 'invalid operand size'
			end if
			if @dest.memsize = 0
				@dest.memsize = @src.size shr 1
			end if
			AVX_512.store_instruction@dest @src.size,VEX_66_0F3A_W0,EVEX_AS_VEX+EVEX_VL,1Dh,@dest.mask,@src.rm,,1,@aux.imm
		else
			err 'invalid combination of operands'
		end if
	end macro

	iterate <instr,vex_mp,evex_f,opcode,msize>, vcvtsd2si,VEX_F2_0F,EVEX_AS_VEX,2Dh,8, vcvtss2si,VEX_F3_0F,EVEX_AS_VEX,2Dh,4, \
						    vcvtsd2usi,VEX_F2_0F,EVEX_REQUIRED,79h,8, vcvtss2usi,VEX_F3_0F,EVEX_REQUIRED,79h,4

		macro instr? dest*,src_er*&
			x86.parse_operand@dest dest
			match src=,er, src_er
				AVX_512.parse_operand@src src
				AVX_512.parse_er@src er,16
			else
				AVX_512.parse_operand@src src_er
			end match
			if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'mmreg')
				if (@dest.size <> 4 & @dest.size <> 8) | (@src.type = 'mem' & @src.size and not msize) | (@src.type = 'mmreg' & @src.size <> 16)
					err 'invalid operand size'
				end if
				if @dest.size = 8
					if x86.mode < 64
						err 'instruction requires long mode'
					end if
					AVX_512.store_instruction@src 16,vex_mp#_W1,evex_f,opcode,0,@dest.rm
				else
					AVX_512.store_instruction@src 16,vex_mp#_W0,evex_f,opcode,0,@dest.rm
				end if
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,vex_mp,evex_f,opcode,msize>, vcvttsd2si,VEX_F2_0F,EVEX_AS_VEX,2Ch,8, vcvttss2si,VEX_F3_0F,EVEX_AS_VEX,2Ch,4, \
						    vcvttsd2usi,VEX_F2_0F,EVEX_REQUIRED,78h,8, vcvttss2usi,VEX_F3_0F,EVEX_REQUIRED,78h,4

		macro instr? dest*,src_sae*&
			x86.parse_operand@dest dest
			match src=,sae, src_sae
				AVX_512.parse_operand@src src
				AVX_512.parse_sae@src sae
			else
				AVX_512.parse_operand@src src_sae
			end match
			if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'mmreg')
				if (@dest.size <> 4 & @dest.size <> 8) | (@src.type = 'mem' & @src.size and not msize) | (@src.type = 'mmreg' & @src.size <> 16)
					err 'invalid operand size'
				end if
				if @dest.size = 8
					if x86.mode < 64
						err 'instruction requires long mode'
					end if
					AVX_512.store_instruction@src 16,vex_mp#_W1,evex_f,opcode,0,@dest.rm
				else
					AVX_512.store_instruction@src 16,vex_mp#_W0,evex_f,opcode,0,@dest.rm
				end if
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	macro vcvtsd2ss? dest*,src*,src2*&
		AVX_512.basic_instruction_er VEX_F2_0F_W0,EVEX_W1,5Ah,8,dest,src,src2
	end macro

	macro vcvtss2sd? dest*,src*,src2*&
		AVX_512.basic_instruction_sae VEX_F3_0F_W0,EVEX_AS_VEX,5Ah,4,dest,src,src2
	end macro

	iterate <instr,evex_f,opcode>, vcvtsi2sd,EVEX_AS_VEX,2Ah, vcvtusi2sd,EVEX_REQUIRED,7Bh

		macro instr? dest*,src*,src_er*&
			AVX_512.parse_operand@dest dest
			AVX_512.parse_operand@src src
			match src2=,er, src_er
				AVX_512.parse_operand@src2 src2
				AVX_512.parse_er@src2 er,8
			else
				AVX_512.parse_operand@src2 src_er
			end match
			if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'reg' | @src2.type = 'mem')
				if @src.size = 0
					err ' operand size not specified'
				else if @dest.size <> 16 | @src.size <> 16 | (@src2.size <> 4 & @src2.size <> 8)
					err 'invalid operand size'
				end if
				if @src2.size = 8
					if x86.mode < 64
						err 'instruction requires long mode'
					end if
					AVX_512.store_instruction@src2 16,VEX_F2_0F_W1,evex_f,opcode,0,@dest.rm,@src.rm
				else
					AVX_512.store_instruction@src2 16,VEX_F2_0F_W0,evex_f,opcode,0,@dest.rm,@src.rm
				end if
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,evex_f,opcode>, vcvtsi2ss,EVEX_AS_VEX,2Ah, vcvtusi2ss,EVEX_REQUIRED,7Bh

		macro instr? dest*,src*,src_er*&
			AVX_512.parse_operand@dest dest
			AVX_512.parse_operand@src src
			match src2=,er, src_er
				AVX_512.parse_operand@src2 src2
				AVX_512.parse_er@src2 er,@src2.size
			else
				AVX_512.parse_operand@src2 src_er
			end match
			if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'reg' | @src2.type = 'mem')
				if @src.size = 0
					err ' operand size not specified'
				else if @dest.size <> 16 | @src.size <> 16 | (@src2.size <> 4 & @src2.size <> 8)
					err 'invalid operand size'
				end if
				if @src2.size = 8
					if x86.mode < 64
						err 'instruction requires long mode'
					end if
					AVX_512.store_instruction@src2 16,VEX_F3_0F_W1,evex_f,opcode,0,@dest.rm,@src.rm
				else
					AVX_512.store_instruction@src2 16,VEX_F3_0F_W0,evex_f,opcode,0,@dest.rm,@src.rm
				end if
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,vex_mpw,evex_f,opcode_rm,opcode_mr>, vmovapd,VEX_66_0F_W0,EVEX_W1+EVEX_VL,28h,29h, vmovaps,VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,28h,29h, \
							    vmovupd,VEX_66_0F_W0,EVEX_W1+EVEX_VL,10h,11h, vmovups,VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,10h,11h, \
							    vmovdqa32,VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL,6Fh,7Fh, vmovdqa64,VEX_66_0F_W1,EVEX_REQUIRED+EVEX_VL,6Fh,7Fh, \
							    vmovdqu32,VEX_F3_0F_W0,EVEX_REQUIRED+EVEX_VL,6Fh,7Fh, vmovdqu64,VEX_F3_0F_W1,EVEX_REQUIRED+EVEX_VL,6Fh,7Fh

		macro instr? dest*,src*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_operand@src src
			if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem')
				if @src.size and not @dest.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode_rm,@dest.mask,@dest.rm
			else if @dest.type = 'mem' & @src.type = 'mmreg'
				if @dest.size and not @src.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@dest @src.size,vex_mpw,evex_f,opcode_mr,@dest.mask,@src.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	macro vmovd? dest*,src*
		AVX_512.parse_operand@dest dest
		AVX_512.parse_operand@src src
		if @dest.type = 'mmreg' & (@src.type = 'reg' | @src.type = 'mem')
			if @dest.size <> 16 | @src.size and not 4
				err 'invalid operand size'
			end if
			@src.memsize = 4
			AVX_512.store_instruction@src 16,VEX_66_0F_W0,EVEX_AS_VEX,6Eh,0,@dest.rm
		else if (@dest.type = 'reg' | @dest.type = 'mem') & @src.type = 'mmreg'
			if @dest.size and not 4 | @src.size <> 16
				err 'operand sizes do not match'
			end if
			@dest.memsize = 4
			AVX_512.store_instruction@dest 16,VEX_66_0F_W0,EVEX_AS_VEX,7Eh,0,@src.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro vmovq? dest*,src*
		AVX_512.parse_operand@dest dest
		AVX_512.parse_operand@src src
		if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem')
			if @dest.size <> 16 | (@src.type = 'mmreg' & @src.size <> 16) | (@src.type = 'mem' and @src.size and not 8)
				err 'invalid operand size'
			end if
			@src.memsize = 8
			AVX_512.store_instruction@src 16,VEX_F3_0F_W0,EVEX_W1,7Eh,0,@dest.rm
		else if @dest.type = 'mem' & @src.type = 'mmreg'
			if @dest.size and not 8 | @src.size <> 16
				err 'invalid operand size'
			end if
			@dest.memsize = 8
			AVX_512.store_instruction@dest 16,VEX_66_0F_W0,EVEX_W1,0D6h,0,@src.rm
		else if @dest.type = 'mmreg' & @src.type = 'reg'
			if @dest.size <> 16 | @src.size <> 8
				err 'invalid operand size'
			end if
			if x86.mode < 64
				err 'instruction requires long mode'
			end if
			AVX_512.store_instruction@src 16,VEX_66_0F_W1,EVEX_W1,6Eh,0,@dest.rm
		else if @dest.type = 'reg' & @src.type = 'mmreg'
			if @dest.size <> 8 | @src.size <> 16
				err 'invalid operand size'
			end if
			if x86.mode < 64
				err 'instruction requires long mode'
			end if
			AVX_512.store_instruction@dest 16,VEX_66_0F_W1,EVEX_W1,7Eh,0,@src.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	macro vmovddup? dest*,src*
		AVX_512.parse_k1z_operand@dest dest
		AVX_512.parse_operand@src src
		if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem')
			if @src.type = 'mem' & @dest.size = 16
				if @src.size and not 8
					err 'invalid operand size'
				end if
				@src.memsize = 8
			else
				if @src.size and not @dest.size
					err 'operand sizes do not match'
				end if
				@src.memsize = @dest.size
			end if
			AVX_512.store_instruction@src @dest.size,VEX_F2_0F_W0,EVEX_W1+EVEX_VL,12h,@dest.mask,@dest.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	iterate <instr,opcode>, vmovhlps,12h, vmovlhps,16h

		macro instr? dest*,src*,src2*
			AVX_512.parse_operand@dest dest
			AVX_512.parse_operand@src src
			AVX_512.parse_operand@src2 src2
			if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'mmreg'
				if @dest.size <> 16
					err 'invalid operand size'
				else if @src.size <> @dest.size | @src2.size <> @dest.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src2 16,VEX_0F_W0,EVEX_AS_VEX,opcode,0,@dest.rm,@src.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,vex_mpw,evex_f,opcode>, vmovhpd,VEX_66_0F_W0,EVEX_W1,16h, vmovhps,VEX_0F_W0,EVEX_AS_VEX,16h, vmovlpd,VEX_66_0F_W0,EVEX_W1,12h, vmovlps,VEX_0F_W0,EVEX_AS_VEX,12h

		macro instr? dest*,src*,src2
			AVX_512.parse_operand@dest dest
			AVX_512.parse_operand@src src
			match , src2
				if @dest.type = 'mem' & @src.type = 'mmreg'
					if @dest.size and not 8 | @src.size <> 16
						err 'invalid operand size'
					end if
					@dest.memsize = 8
					AVX_512.store_instruction@dest 16,vex_mpw,evex_f,opcode+1,0,@src.rm
				else
					err 'invalid combination of operands'
				end if
			else
				AVX_512.parse_operand@src2 src2
				if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'mem'
					if @dest.size <> 16 | @src.size <> 16 | @src2.size and not 8
						err 'invalid operand size'
					end if
					@src2.memsize = 8
					AVX_512.store_instruction@src2 16,vex_mpw,evex_f,opcode,0,@dest.rm,@src.rm
				else
					err 'invalid combination of operands'
				end if
			end match
		end macro

	end iterate

	iterate <instr,vex_mpw,evex_f,opcode>, vmovntdq,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL,0E7h, vmovntpd,VEX_66_0F_W0,EVEX_W1+EVEX_VL,2Bh, vmovntps,VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,2Bh

		macro instr? dest*,src*
			AVX_512.parse_operand@dest dest
			AVX_512.parse_operand@src src
			if @dest.type = 'mem' & @src.type = 'mmreg'
				if @dest.size and not @src.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@dest @src.size,vex_mpw,evex_f,opcode,0,@src.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	macro vmovntdqa? dest*,src*
		AVX_512.parse_operand@dest dest
		AVX_512.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_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,2Ah,0,@dest.rm
		else
			err 'invalid combination of operands'
		end if
	end macro

	iterate <instr,vex_mpw,evex_f,msize>, vmovsd,VEX_F2_0F_W0,EVEX_W1,8, vmovss,VEX_F3_0F_W0,EVEX_AS_VEX,4

		macro instr? dest*,src*,src2
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_operand@src src
			match , src2
				if @dest.type = 'mmreg' & @src.type = 'mem'
					if @dest.size <> 16 | @src.size and not msize
						err 'invalid operand size'
					end if
					@src.memsize = msize
					AVX_512.store_instruction@src 16,vex_mpw,evex_f,10h,@dest.mask,@dest.rm
				else if @dest.type = 'mem' & @src.type = 'mmreg'
					if @dest.size and not msize | @src.size <> 16
						err 'invalid operand size'
					end if
					@dest.memsize = msize
					AVX_512.store_instruction@dest 16,vex_mpw,evex_f,11h,@dest.mask,@src.rm
				else
					err 'invalid combination of operands'
				end if
			else
				AVX_512.parse_operand@src2 src2
				if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'mmreg'
					if @dest.size <> 16 | @src.size <> 16 | @src2.size <> 16
						err 'invalid operand size'
					end if
					AVX_512.store_instruction@src2 16,vex_mpw,evex_f,10h,@dest.mask,@dest.rm,@src.rm
				else
					err 'invalid combination of operands'
				end if
			end match
		end macro

	end iterate

	macro vmovshdup? dest*,src*
		AVX_512.single_source_instruction VEX_F3_0F_W0,EVEX_AS_VEX+EVEX_VL,16h,0,dest,src
	end macro

	macro vmovsldup? dest*,src*
		AVX_512.single_source_instruction VEX_F3_0F_W0,EVEX_AS_VEX+EVEX_VL,12h,0,dest,src
	end macro

	iterate <instr,unit,evex_f,opcode_rrm,opcode_rri>, vpermilps,4,EVEX_AS_VEX+EVEX_VL,0Ch,4, vpermilpd,8,EVEX_W1+EVEX_VL,0Dh,5

		macro instr? dest*,src*,src2*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_bcst_operand@src src,unit
			AVX_512.parse_bcst_operand@src2 src2,unit
			if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
				if @src.size <> @dest.size | @src2.size and not @dest.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src2 @dest.size,VEX_66_0F38_W0,evex_f,opcode_rrm,@dest.mask,@dest.rm,@src.rm
			else if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @src2.type = 'imm'
				if @src2.size and not 1
					err 'invalid operand size'
				else if @src.size and not @dest.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src @dest.size,VEX_66_0F3A_W0,evex_f,opcode_rri,@dest.mask,@dest.rm,,1,@src2.imm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,opcode>, vpaddd,0FEh, vpsubd,0FAh, vpunpckhdq,6Ah, vpunpckldq,62h

		macro instr? dest*,src*,src2*
			AVX_512.basic_instruction_bcst VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src,src2
		end macro

	end iterate

	iterate <instr,opcode>, vpaddq,0D4h, vpmuludq,0F4h, vpsubq,0FBh, vpunpckhqdq,6Dh, vpunpcklqdq,6Ch

		macro instr? dest*,src*,src2*
			AVX_512.basic_instruction_bcst VEX_66_0F_W0,EVEX_W1+EVEX_VL,opcode,8,dest,src,src2
		end macro

	end iterate

	iterate <instr,opcode>, vpandd,0DBh, vpandnd,0DFh, vpord,0EBh, vpxord,0EFh

		macro instr? dest*,src*,src2*
			AVX_512.basic_instruction_bcst VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL,opcode,4,dest,src,src2
		end macro

	end iterate

	iterate <instr,opcode>, vpandq,0DBh, vpandnq,0DFh, vporq,0EBh, vpxorq,0EFh

		macro instr? dest*,src*,src2*
			AVX_512.basic_instruction_bcst VEX_66_0F_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2
		end macro

	end iterate

	iterate <instr,opcode>, vpmaxsd,3Dh, vpmaxud,3Fh, vpminsd,39h, vpminud,3Bh, vpmulld,40h

		macro instr? dest*,src*,src2*
			AVX_512.basic_instruction_bcst VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src,src2
		end macro

	end iterate

	iterate <instr,opcode>, vpmuldq,28h

		macro instr? dest*,src*,src2*
			AVX_512.basic_instruction_bcst VEX_66_0F38_W0,EVEX_W1+EVEX_VL,opcode,8,dest,src,src2
		end macro

	end iterate

	iterate <instr,opcode>, vpmuldq,28h, vpmaxsq,3Dh, vpmaxuq,3Fh, vpminsq,39h, vpminuq,3Bh, vpmullq,40h

		macro instr? dest*,src*,src2*
			AVX_512.basic_instruction_bcst VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2
		end macro

	end iterate

	iterate <instr,opcode>, vpabsd,1Eh

		macro instr? dest*,src*
			AVX_512.single_source_instruction_bcst VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src
		end macro

	end iterate

	iterate <instr,opcode>, vpabsq,1Fh

		macro instr? dest*,src*
			AVX_512.single_source_instruction_bcst VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src
		end macro

	end iterate

	iterate <instr,vex_mpw>, vpshufd,VEX_66_0F_W0

		macro instr? dest*,src*,aux*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_operand@src src
			x86.parse_operand@aux aux
			if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm'
				if @aux.size and not 1
					err 'invalid operand size'
				else if @src.size and not @dest.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_AS_VEX+EVEX_VL,70h,@dest.mask,@dest.rm,,1,@aux.imm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,opcode>, vpsllvd,47h, vpsrlvd,45h, vpsravd,46h

		macro instr? dest*,src*,src2*
			AVX_512.basic_instruction_bcst VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src,src2
		end macro

	end iterate

	iterate <instr,evex_f,opcode>, vpsllvq,EVEX_AS_VEX+EVEX_VL,47h, vpsrlvq,EVEX_AS_VEX+EVEX_VL,45h, vpsravq,EVEX_REQUIRED+EVEX_VL,46h

		macro instr? dest*,src*,src2*
			AVX_512.basic_instruction_bcst VEX_66_0F38_W1,evex_f,opcode,8,dest,src,src2
		end macro

	end iterate

	iterate <instr,unit,vex_mpw,opcode>, vpermi2d,4,VEX_66_0F38_W0,76h, vpermi2q,8,VEX_66_0F38_W1,76h, \
					     vpermt2d,4,VEX_66_0F38_W0,7Eh, vpermt2q,8,VEX_66_0F38_W1,7Eh, \
					     vprorvd,4,VEX_66_0F38_W0,14h, vprorvq,8,VEX_66_0F38_W1,14h, \
					     vprolvd,4,VEX_66_0F38_W0,15h, vprolvq,8,VEX_66_0F38_W1,15h

		macro instr? dest*,src*,src2*
			AVX_512.basic_instruction_bcst vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src,src2
		end macro

	end iterate

	iterate <instr,unit,vex_mpw,postbyte>, vprord,4,VEX_66_0F_W0,0, vprorq,8,VEX_66_0F_W1,0, vprold,4,VEX_66_0F_W0,1, vprolq,8,VEX_66_0F_W1,1

		macro instr? dest*,src*,aux*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_bcst_operand@src src,unit
			x86.parse_operand@aux aux
			if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm'
				if @src.size and not @dest.size | @aux.size and not 1
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,72h,@dest.mask,postbyte,@dest.rm,1,@aux.imm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,opcode_rrm,opcode,postbyte>, vpslld,0F2h,72h,6, vpsrad,0E2h,72h,4, vpsrld,0D2h,72h,2

		macro instr? dest*,src*,src2*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_operand@src2 src2
			if @src2.type = 'imm'
				AVX_512.parse_bcst_operand@src src,4
			else
				AVX_512.parse_operand@src src
			end if
			if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
				@src2.memsize = 16
				if @src2.size and not @src2.memsize
					err 'invalid operand size'
				else if @src.size <> @dest.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src2 @dest.size,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode_rrm,@dest.mask,@dest.rm,@src.rm
			else if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') & @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
				if @src.type = 'mem'
					AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,postbyte,@dest.rm,1,@src2.imm
				else
					AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode,@dest.mask,postbyte,@dest.rm,1,@src2.imm
				end if
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,opcode_rrm,opcode,postbyte>, vpsllq,0F3h,73h,6, vpsraq,0E2h,72h,4, vpsrlq,0D3h,73h,2

		macro instr? dest*,src*,src2*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_operand@src2 src2
			if @src2.type = 'imm'
				AVX_512.parse_bcst_operand@src src,8
			else
				AVX_512.parse_operand@src src
			end if
			if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
				@src2.memsize = 16
				if @src2.size and not @src2.memsize
					err 'invalid operand size'
				else if @src.size <> @dest.size
					err 'operand sizes do not match'
				end if
				if `instr = 'vpsraq'
					AVX_512.store_instruction@src2 @dest.size,VEX_66_0F_W1,EVEX_REQUIRED+EVEX_VL,opcode_rrm,@dest.mask,@dest.rm,@src.rm
				else
					AVX_512.store_instruction@src2 @dest.size,VEX_66_0F_W0,EVEX_W1+EVEX_VL,opcode_rrm,@dest.mask,@dest.rm,@src.rm
				end if
			else if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') & @src2.type = 'imm'
				if @src2.size and not 1
					err 'invalid operand size'
				else if @src.size and not @dest.size
					err 'operand sizes do not match'
				end if
				if @src.type = 'mem' | `instr = 'vpsraq'
					AVX_512.store_instruction@src @dest.size,VEX_66_0F_W1,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,postbyte,@dest.rm,1,@src2.imm
				else
					AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_W1+EVEX_VL,opcode,@dest.mask,postbyte,@dest.rm,1,@src2.imm
				end if
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,opcode>, vpcmpeqd,76h, vpcmpgtd,66h

		macro instr? dest*,src*,src2*
			AVX_512.parse_k1_operand@dest dest
			AVX_512.parse_operand@src src
			AVX_512.parse_bcst_operand@src2 src2,4
			if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
				if @src2.size and not @src.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src2 @src.size,VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm
			else if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
				if @src.size <> @dest.size | @src2.size and not @dest.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src2 @src.size,VEX_66_0F_W0,EVEX_FORBIDDEN,opcode,@dest.mask,@dest.rm,@src.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,opcode>, vpcmpeqq,29h, vpcmpgtq,37h

		macro instr? dest*,src*,src2*
			AVX_512.parse_k1_operand@dest dest
			AVX_512.parse_operand@src src
			AVX_512.parse_bcst_operand@src2 src2,8
			if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
				if @src2.size and not @src.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src2 @src.size,VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm
			else if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
				if @src.size <> @dest.size | @src2.size and not @dest.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src2 @src.size,VEX_66_0F38_W0,EVEX_FORBIDDEN,opcode,@dest.mask,@dest.rm,@src.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,unit,vex_mpw,opcode>, vptestnmd,4,VEX_F3_0F38_W0,27h, vptestnmq,8,VEX_F3_0F38_W1,27h, vptestmd,4,VEX_66_0F38_W0,27h, vptestmq,8,VEX_66_0F38_W1,27h

		macro instr? dest*,src*,src2*
			AVX_512.parse_k1_operand@dest dest
			AVX_512.parse_operand@src src
			AVX_512.parse_bcst_operand@src2 src2,unit
			if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
				if @src2.size and not @src.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src2 @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,unit,vex_mpw,opcode>, vpcmpd,4,VEX_66_0F3A_W0,1Fh, vpcmpud,4,VEX_66_0F3A_W0,1Eh, vpcmpq,8,VEX_66_0F3A_W1,1Fh, vpcmpuq,8,VEX_66_0F3A_W1,1Eh

		macro instr? dest*,src*,src2*,aux*
			AVX_512.parse_k1_operand@dest dest
			AVX_512.parse_operand@src src
			AVX_512.parse_bcst_operand@src2 src2,unit
			x86.parse_operand@aux aux
			if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm'
				if @src2.size and not @src.size | @aux.size and not 1
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src2 @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,opcode,msize>, vpmovsxbd,21h,4, vpmovsxbq,22h,2, vpmovsxwd,23h,8, vpmovsxwq,24h,4, vpmovsxdq,25h,8, \
				      vpmovzxbd,31h,4, vpmovzxbq,32h,2, vpmovzxwd,33h,8, vpmovzxwq,34h,4, vpmovzxdq,35h,8

		macro instr? dest*,src*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_operand@src src
			if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
				@src.memsize = msize * (@dest.size shr 4)
				if (@src.type = 'mmreg' & @src.size <> (@src.memsize-1) and not 15 + 16) | (@src.type = 'mem' & @src.size and not @src.memsize)
					err 'invalid operand size'
				end if
				AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,@dest.mask,@dest.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,opcode>, vpermq,0, vpermpd,1

		macro instr? dest*,src*,aux*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_bcst_operand@src src,8
			x86.parse_operand@aux aux
			if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm'
				if @dest.size < 32 | @aux.size and not 1
					err 'invalid operand size'
				else if @src.size and not @dest.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src @dest.size,VEX_66_0F3A_W1,EVEX_AS_VEX+EVEX_VL,opcode,@dest.mask,@dest.rm,,1,@aux.imm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,opcode>, vpermd,36h, vpermps,16h

		macro instr? dest*,src*,src2*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_operand@src src
			AVX_512.parse_bcst_operand@src2 src2,4
			if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
				if @dest.size < 32
					err 'invalid operand size'
				else if @src.size <> @dest.size | @src2.size and not @dest.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@src2 @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,lcode>, vfmaddsub,6, vfmsubadd,7, vfmaddsub,8, vfmsub,0Ah, vfnmadd,0Ch, vfnmsub,0Eh

		iterate <order,hcode>, 132,90h, 213,0A0h, 231,0B0h

			macro instr#order#pd? dest*,src*,src2*&
				AVX_512.basic_instruction_bcst_er VEX_66_0F38_W1,EVEX_AS_VEX+EVEX_VL,hcode+lcode,8,dest,src,src2
			end macro

			macro instr#order#ps? dest*,src*,src2*&
				AVX_512.basic_instruction_bcst_er VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,hcode+lcode,4,dest,src,src2
			end macro

			if lcode > 7

				macro instr#order#sd? dest*,src*,src2*&
					AVX_512.basic_instruction_er VEX_66_0F38_W1,EVEX_AS_VEX,hcode+lcode+1,8,dest,src,src2
				end macro

				macro instr#order#ss? dest*,src*,src2*&
					AVX_512.basic_instruction_er VEX_66_0F38_W0,EVEX_AS_VEX,hcode+lcode+1,4,dest,src,src2
				end macro

			end if

		end iterate

	end iterate

	iterate <instr,unit,vex_mpw,opcode>, valignd,4,VEX_66_0F3A_W0,3, vpternlogd,4,VEX_66_0F3A_W0,25h, vpternlogq,8,VEX_66_0F3A_W1,25h

		macro instr? dest*,src*,src2*,aux*&
			AVX_512.basic_instruction_bcst_imm8 vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src,src2,aux
		end macro

	end iterate

	iterate <instr,opcode>, valignq,3

		macro instr? dest*,src*,src2*,aux*&
			AVX_512.basic_instruction_bcst_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2,aux
		end macro

	end iterate

	iterate <instr,opcode>, vblendmps,65h, vpblendmd,64h

		macro instr? dest*,src*,src2*&
			AVX_512.basic_instruction_bcst VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,4,dest,src,src2
		end macro

	end iterate

	iterate <instr,opcode>, vblendmpd,65h, vpblendmq,64h

		macro instr? dest*,src*,src2*&
			AVX_512.basic_instruction_bcst VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2
		end macro

	end iterate

	iterate <instr,unit,vex_mpw,opcode>, vrcp14ps,4,VEX_66_0F38_W0,4Ch, vrcp14pd,8,VEX_66_0F38_W1,4Ch, vrsqrt14ps,4,VEX_66_0F38_W0,4Eh, vrsqrt14pd,8,VEX_66_0F38_W1,4Eh

		macro instr? dest*,src*&
			AVX_512.single_source_instruction_bcst vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src
		end macro

	end iterate

	iterate <instr,unit,vex_mpw,opcode>, vrcp14ss,4,VEX_66_0F38_W0,4Dh, vrcp14sd,8,VEX_66_0F38_W1,4Dh, vrsqrt14ss,4,VEX_66_0F38_W0,4Fh, vrsqrt14sd,8,VEX_66_0F38_W1,4Fh

		macro instr? dest*,src*&
			AVX_512.basic_instruction vex_mpw,EVEX_REQUIRED,opcode,unit,dest,src
		end macro

	end iterate

	iterate <instr,vex_mpw,opcode>, vcompressps,VEX_66_0F_W0,8Ah, vcompresspd,VEX_66_0F_W1,8Ah, vpcompressd,VEX_66_0F38_W0,8Bh, vpcompressq,VEX_66_0F38_W1,8Bh

		macro instr? dest*,src*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_operand@src src
			if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg'
				if @dest.size and not @src.size
					err 'operand sizes do not match'
				end if
				AVX_512.store_instruction@dest @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@src.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,vex_mpw,opcode>, vexpandps,VEX_66_0F38_W0,88h, vexpandpd,VEX_66_0F38_W1,88h, vpexpandd,VEX_66_0F38_W0,89h, vpexpandq,VEX_66_0F38_W1,89h

		macro instr? dest*,src*
			AVX_512.single_source_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src
		end macro

	end iterate

	iterate <instr,opcode>, fixupimm,54h

		macro v#instr#pd? dest*,src*,src2*,aux*&
			AVX_512.basic_instruction_bcst_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2,aux
		end macro

		macro v#instr#ps? dest*,src*,src2*,aux*&
			AVX_512.basic_instruction_bcst_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED+EVEX_VL,opcode,4,dest,src,src2,aux
		end macro

		macro v#instr#sd? dest*,src*,src2*,aux*&
			AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED,opcode+1,8,dest,src,src2,aux
		end macro

		macro v#instr#ss? dest*,src*,src2*,aux*&
			AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED,opcode+1,4,dest,src,src2,aux
		end macro

	end iterate

	iterate <instr,opcode>, getexp,42h

		macro v#instr#pd? dest*,src*&
			AVX_512.single_source_instruction_bcst_sae VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src
		end macro

		macro v#instr#ps? dest*,src*&
			AVX_512.single_source_instruction_bcst_sae VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,4,dest,src
		end macro

		macro v#instr#sd? dest*,src*,src2*&
			AVX_512.basic_instruction_sae VEX_66_0F38_W1,EVEX_REQUIRED,opcode+1,8,dest,src,src2
		end macro

		macro v#instr#ss? dest*,src*,src2*&
			AVX_512.basic_instruction_sae VEX_66_0F38_W0,EVEX_REQUIRED,opcode+1,4,dest,src,src2
		end macro

	end iterate

	iterate <instr,opcode_ps,opcode_pd,opcode_ss,opcode_sd>, getmant,26h,26h,27h,27h, rndscale,8,9,0Ah,0Bh

		macro v#instr#pd? dest*,src*,aux*&
			AVX_512.single_source_instruction_bcst_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED+EVEX_VL,opcode_pd,8,dest,src,aux
		end macro

		macro v#instr#ps? dest*,src*,aux*&
			AVX_512.single_source_instruction_bcst_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED+EVEX_VL,opcode_ps,4,dest,src,aux
		end macro

		macro v#instr#sd? dest*,src*,src2*,aux*&
			AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED,opcode_sd,8,dest,src,src2,aux
		end macro

		macro v#instr#ss? dest*,src*,src2*,aux*&
			AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED,opcode_ss,4,dest,src,src2,aux
		end macro

	end iterate

	iterate <instr,unit,vex_mpw>, vscalefpd,8,VEX_66_0F38_W1, vscalefps,4,VEX_66_0F38_W0

		macro instr? dest*,src*,src2*&
			AVX_512.basic_instruction_bcst_er vex_mpw,EVEX_REQUIRED+EVEX_VL,2Ch,unit,dest,src,src2
		end macro

	end iterate

	iterate <instr,unit,vex_mpw>, vscalefsd,8,VEX_66_0F38_W1, vscalefss,4,VEX_66_0F38_W0

		macro instr? dest*,src*,src2*&
			AVX_512.basic_instruction_er vex_mpw,EVEX_REQUIRED,2Dh,unit,dest,src,src2
		end macro

	end iterate

	iterate <instr,ratio,opcode>, vpmovusdb,4,11h, vpmovsdb,4,21h, vpmovdb,4,31h, \
				      vpmovusqb,8,12h, vpmovsqb,8,22h, vpmovqb,8,32h, \
				      vpmovusdw,2,13h, vpmovsdw,2,23h, vpmovdw,2,33h, \
				      vpmovusqw,4,14h, vpmovsqw,4,24h, vpmovqw,4,34h, \
				      vpmovusqd,2,15h, vpmovsqd,2,25h, vpmovqd,2,35h

		macro instr? dest*,src*
			AVX_512.parse_k1z_operand@dest dest
			AVX_512.parse_operand@src src
			if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg'
				@dest.memsize = @src.size / ratio
				if (@dest.type = 'mmreg' & @dest.size <> (@dest.memsize-1) and not 15 + 16) | (@dest.type = 'mem' & @dest.size and not @dest.memsize)
					err 'invalid operand size'
				end if
				AVX_512.store_instruction@dest @src.size,VEX_F3_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@src.rm
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,opcode,asize>, vpgatherdd,90h,4, vpgatherqd,91h,8, vgatherdps,92h,4, vgatherqps,93h,8

		macro instr? dest*,src*,aux
			match , aux
				AVX_512.parse_k1_operand@dest dest
				AVX_512.parse_vsib_operand@src src
				if @dest.type = 'mmreg' & @dest.mask & @src.type = 'mem'
					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 @dest.rm = @src.index
						err 'disallowed combination of registers'
					end if
					@src.memsize = 4
					AVX_512.store_instruction@src @src.visize,VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.index and 10000b
				else
					err 'invalid combination of operands'
				end if
			else
				AVX.parse_operand@dest dest
				AVX.parse_vsib_operand@src src
				AVX.parse_operand@aux aux
				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 match
		end macro

	end iterate

	iterate <instr,opcode,asize>, vpgatherdq,90h,4, vpgatherqq,91h,8, vgatherdpd,92h,4, vgatherqpd,93h,8

		macro instr? dest*,src*,aux
			match , aux
				AVX_512.parse_k1_operand@dest dest
				AVX_512.parse_vsib_operand@src src
				if @dest.type = 'mmreg' & @dest.mask & @src.type = 'mem'
					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 @dest.rm = @src.index
						err 'disallowed combination of registers'
					end if
					@src.memsize = 8
					AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.index and 10000b
				else
					err 'invalid combination of operands'
				end if
			else
				AVX.parse_operand@dest dest
				AVX.parse_vsib_operand@src src
				AVX.parse_operand@aux aux
				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 match
		end macro

	end iterate

	iterate <instr,opcode,asize>, vpscatterdd,0A0h,4, vpscatterqd,0A1h,8, vscatterdps,0A2h,4, vscatterqps,0A3h,8

		macro instr? dest*,src*
			AVX_512.parse_k1_vsib_operand@dest dest
			AVX_512.parse_operand@src src
			if @dest.type = 'mem' & @dest.mask & @src.type = 'mmreg'
				if @dest.size and not 4 | (@src.size > 16 & @src.size * (asize shr 2) > @dest.visize) | (@dest.visize > 16 & @src.size * (asize shr 2) < @dest.visize)
					err 'invalid operand size'
				else if @src.rm = @dest.index
					err 'disallowed combination of registers'
				end if
				@dest.memsize = 4
				AVX_512.store_instruction@dest @dest.visize,VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@src.rm,@dest.index and 10000b
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

	iterate <instr,opcode,asize>, vpscatterdq,0A0h,4, vpscatterqq,0A1h,8, vscatterdpd,0A2h,4, vscatterqpd,0A3h,8

		macro instr? dest*,src*
			AVX_512.parse_k1_vsib_operand@dest dest
			AVX_512.parse_operand@src src
			if @dest.type = 'mem' & @dest.mask & @src.type = 'mmreg'
				if @dest.size and not 8 | (@src.size > 16 & @src.size * (asize shr 2) > @dest.visize * 2) | (@dest.visize > 16 & @src.size * (asize shr 2) < @dest.visize * 2)
					err 'invalid operand size'
				else if @src.rm = @dest.index
					err 'disallowed combination of registers'
				end if
				@dest.memsize = 8
				AVX_512.store_instruction@dest @src.size,VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@src.rm,@dest.index and 10000b
			else
				err 'invalid combination of operands'
			end if
		end macro

	end iterate

end if
