asm_dip/toolchain/fasmg.kl0e/examples/x86/include/ext/avx2.inc
2024-11-24 23:13:28 -05:00

503 lines
16 KiB
PHP

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 <instr,opcode,asize>, 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 <instr,opcode,asize>, 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 <instr,opcode>, 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 <instr,opcode>, 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 <instr,opcode>, 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 <instr,opcode>, 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 <instr,vex_mpw>, 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 <instr,vex_mpw,opcode>, 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 <instr,opcode,msize>, 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 <instr,postbyte>, 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 <instr,opcode_rrm,opcode,postbyte>, 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 <instr,w>, 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 <instr,opcode,msize>, 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 <instr,opcode>, 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 <instr,opcode>, 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