added fasm2 as well
This commit is contained in:
46
toolchain/fasm2/include/iset/3dnow.inc
Normal file
46
toolchain/fasm2/include/iset/3dnow.inc
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
iterate <instr,opcode>, pf2id,1Dh, pfacc,0AEh, pfadd,9Eh, pfmax,0A4h, pfmin,94h, \
|
||||
pfmul,0B4h, pfrcp,96h, pfsub,9Ah, pi2fd,0Dh, pi2fw,0Ch, \
|
||||
pfsubr,0AAh, pavgusb,0BFh, pfcmpeq,0B0h, pfcmpge,90h, pfcmpgt,0A0h, \
|
||||
pfrsqrt,97h, pmulhrw,0B7h, pfrcpit2,0B6h, pfrsqit1,0A7h
|
||||
|
||||
calminstruction instr? dest*,src*
|
||||
call x86.require.3DNow
|
||||
call MMX.parse_operand@dest, dest
|
||||
call MMX.parse_operand@src, src
|
||||
check @src.size and not @dest.size
|
||||
jno size_ok
|
||||
err 'operand sizes do not match'
|
||||
size_ok:
|
||||
check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
jno invalid_combination_of_operands
|
||||
xcall x86.store_instruction@src, <0Fh,0Fh>,@dest.rm,(1),(opcode)
|
||||
exit
|
||||
invalid_combination_of_operands:
|
||||
err 'invalid combination of operands'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
calminstruction femms?
|
||||
call x86.require.3DNow
|
||||
emit 1, 0Fh
|
||||
emit 1, 0Eh
|
||||
end calminstruction
|
||||
|
||||
iterate <instr,postbyte>, prefetch,0, prefetchw,1
|
||||
calminstruction instr? src*
|
||||
call x86.require.3DNow
|
||||
call MMX.parse_operand@src, src
|
||||
check @src.type = 'mem'
|
||||
jno invalid_operand
|
||||
check @src.size and not 1
|
||||
jno size_ok
|
||||
err 'invalid operand size'
|
||||
size_ok:
|
||||
xcall x86.store_instruction@src, <0Fh,0Dh>,(postbyte)
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
end iterate
|
58
toolchain/fasm2/include/iset/aes.inc
Normal file
58
toolchain/fasm2/include/iset/aes.inc
Normal file
@ -0,0 +1,58 @@
|
||||
|
||||
iterate <instr,supp>, aesdec,0DEh, aesenc,0DCh, aesdeclast,0DFh, aesenclast,0DDh
|
||||
|
||||
macro instr? dest*,src*
|
||||
require AESNI
|
||||
SSE.basic_instruction 66h,<38h,supp>,16,dest,src
|
||||
end macro
|
||||
|
||||
macro v#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 = 'mem' | @src2.type = 'mmreg')
|
||||
if @dest.size <> @src.size | @src2.size and not @dest.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
@src2.memsize = 0
|
||||
if x86.ext and x86.VAES.ext
|
||||
AVX_512.store_instruction@src2 @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,0,@dest.rm,@src.rm
|
||||
else
|
||||
require AESNI
|
||||
AVX_512.store_instruction@src2 @dest.size,VEX_66_0F38_W0,EVEX_FORBIDDEN,opcode,0,@dest.rm,@src.rm
|
||||
end if
|
||||
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,opcode>, aesimc,0DBh
|
||||
|
||||
macro instr? dest*,src*
|
||||
require AESNI
|
||||
SSE.basic_instruction 66h,<38h,supp>,16,dest,src
|
||||
end macro
|
||||
|
||||
macro v#instr? dest*,src*
|
||||
require AESNI
|
||||
AVX_512.single_source_instruction VEX_66_0F38_W0,EVEX_FORBIDDEN,opcode,16,dest,src
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,supp>, aeskeygenassist,0DFh
|
||||
|
||||
macro instr? dest*,src*,imm*
|
||||
require AESNI
|
||||
SSE.basic_instruction_imm8 66h,<3Ah,supp>,16,dest,src,imm
|
||||
end macro
|
||||
|
||||
macro v#instr? dest*,src*,imm*
|
||||
require AESNI
|
||||
AVX_512.single_source_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN,opcode,16,dest,src,imm
|
||||
end macro
|
||||
|
||||
end iterate
|
4319
toolchain/fasm2/include/iset/avx.inc
Normal file
4319
toolchain/fasm2/include/iset/avx.inc
Normal file
File diff suppressed because it is too large
Load Diff
290
toolchain/fasm2/include/iset/bmi.inc
Normal file
290
toolchain/fasm2/include/iset/bmi.inc
Normal file
@ -0,0 +1,290 @@
|
||||
|
||||
macro andn? dest*,src*,src2*
|
||||
require BMI1
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
x86.parse_operand@src2 src2
|
||||
if @dest.type = 'reg' & @src.type = 'reg' & (@src2.type = 'mem' | @src2.type = 'reg')
|
||||
if @dest.size < 4
|
||||
err 'invalid operand size'
|
||||
else if @src.size <> @dest.size | @src2.size and not @dest.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
if @dest.size = 8
|
||||
if x86.mode < 64
|
||||
err 'instruction requires long mode'
|
||||
end if
|
||||
AVX.store_instruction@src2 16,VEX_0F38_W1,0F2h,@dest.rm,@src.rm
|
||||
else
|
||||
AVX.store_instruction@src2 16,VEX_0F38_W0,0F2h,@dest.rm,@src.rm
|
||||
end if
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro bextr? dest*,src*,src2*
|
||||
require BMI1
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
x86.parse_operand@src2 src2
|
||||
if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') & @src2.type = 'reg'
|
||||
if @dest.size < 4
|
||||
err 'invalid operand size'
|
||||
else if @src.size and not @dest.size | @src2.size <> @dest.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
if @dest.size = 8
|
||||
if x86.mode < 64
|
||||
err 'instruction requires long mode'
|
||||
end if
|
||||
AVX.store_instruction@src 16,VEX_0F38_W1,0F7h,@dest.rm,@src2.rm
|
||||
else
|
||||
AVX.store_instruction@src 16,VEX_0F38_W0,0F7h,@dest.rm,@src2.rm
|
||||
end if
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
iterate <instr,opcode,postbyte>, blsi,0F3h,3, blsmsk,0F3h,2, blsr,0F3h,1
|
||||
|
||||
macro instr? dest*,src*
|
||||
require BMI1
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg')
|
||||
if @dest.size < 4
|
||||
err 'invalid operand size'
|
||||
else if @src.size and not @dest.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
if @dest.size = 8
|
||||
if x86.mode < 64
|
||||
err 'instruction requires long mode'
|
||||
end if
|
||||
AVX.store_instruction@src 16,VEX_0F38_W1,opcode,postbyte,@dest.rm
|
||||
else
|
||||
AVX.store_instruction@src 16,VEX_0F38_W0,opcode,postbyte,@dest.rm
|
||||
end if
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,opcode>, lzcnt,0BDh, tzcnt,0BCh
|
||||
|
||||
macro instr? dest*,src*
|
||||
require BMI1
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
if @dest.type = 'reg' & ( @src.type = 'reg' | @src.type = 'mem' )
|
||||
if @src.size and not @dest.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
@src.opcode_prefix = 0F3h
|
||||
if @dest.size > 1
|
||||
x86.select_operand_prefix@src @dest.size
|
||||
x86.store_instruction@src <0Fh,opcode>,@dest.rm
|
||||
else
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,opcode>, bzhi,0F5h
|
||||
|
||||
macro instr? dest*,src*,src2*
|
||||
require BMI2
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
x86.parse_operand@src2 src2
|
||||
if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') & @src2.type = 'reg'
|
||||
if @dest.size < 4
|
||||
err 'invalid operand size'
|
||||
else if @src.size and not @dest.size | @src2.size <> @dest.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
if @dest.size = 8
|
||||
if x86.mode < 64
|
||||
err 'instruction requires long mode'
|
||||
end if
|
||||
AVX.store_instruction@src 16,VEX_0F38_W1,opcode,@dest.rm,@src2.rm
|
||||
else
|
||||
AVX.store_instruction@src 16,VEX_0F38_W0,opcode,@dest.rm,@src2.rm
|
||||
end if
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,vex_mp,opcode>, mulx,VEX_F2_0F38,0F6h, pdep,VEX_F2_0F38,0F5h, pext,VEX_F3_0F38,0F5h
|
||||
|
||||
macro instr? dest*,src*,src2*
|
||||
require BMI2
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
x86.parse_operand@src2 src2
|
||||
if @dest.type = 'reg' & @src.type = 'reg' & (@src2.type = 'mem' | @src2.type = 'reg')
|
||||
if @dest.size < 4
|
||||
err 'invalid operand size'
|
||||
else if @src.size <> @dest.size | @src2.size and not @dest.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
if @dest.size = 8
|
||||
if x86.mode < 64
|
||||
err 'instruction requires long mode'
|
||||
end if
|
||||
AVX.store_instruction@src2 16,vex_mp#_W1,opcode,@dest.rm,@src.rm
|
||||
else
|
||||
AVX.store_instruction@src2 16,vex_mp#_W0,opcode,@dest.rm,@src.rm
|
||||
end if
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
macro rorx? dest*,src*,src2*
|
||||
require BMI2
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
x86.parse_operand@src2 src2
|
||||
if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') & @src2.type = 'imm'
|
||||
if @dest.size < 4 | @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 @dest.size = 8
|
||||
if x86.mode < 64
|
||||
err 'instruction requires long mode'
|
||||
end if
|
||||
AVX.store_instruction@src 16,VEX_F2_0F3A_W1,0F0h,@dest.rm,,1,@src2.imm
|
||||
else
|
||||
AVX.store_instruction@src 16,VEX_F2_0F3A_W0,0F0h,@dest.rm,,1,@src2.imm
|
||||
end if
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
iterate <instr,vex_mp,opcode>, sarx,VEX_F3_0F38,0F7h, shlx,VEX_66_0F38,0F7h, shrx,VEX_F2_0F38,0F7h
|
||||
|
||||
macro instr? dest*,src*,src2*
|
||||
require BMI2
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
x86.parse_operand@src2 src2
|
||||
if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') & @src2.type = 'reg'
|
||||
if @dest.size < 4
|
||||
err 'invalid operand size'
|
||||
else if @src.size and not @dest.size | @src2.size <> @dest.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
if @dest.size = 8
|
||||
if x86.mode < 64
|
||||
err 'instruction requires long mode'
|
||||
end if
|
||||
AVX.store_instruction@src 16,vex_mp#_W1,opcode,@dest.rm,@src2.rm
|
||||
else
|
||||
AVX.store_instruction@src 16,vex_mp#_W0,opcode,@dest.rm,@src2.rm
|
||||
end if
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,vex_mpw,opcode>, vpermb,VEX_66_0F38_W0,8Dh, vpermi2b,VEX_66_0F38_W0,75h, vpermt2b,VEX_66_0F38_W0,7Dh
|
||||
|
||||
macro instr? dest*,src*,src2*
|
||||
require AVX512_VBMI
|
||||
AVX_512.basic_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src,src2
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,opcode>, vpmultishiftqb,83h
|
||||
|
||||
macro instr? dest*,src*,src2*
|
||||
require AVX512_VBMI
|
||||
AVX_512.basic_instruction_bcst VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,vex_mpw,opcode>, vpshldw,VEX_66_0F3A_W1,70h, vpshrdw,VEX_66_0F3A_W1,72h
|
||||
|
||||
macro instr? dest*,src*,src2*,aux*&
|
||||
require AVX512_VBMI2
|
||||
AVX_512.basic_instruction_imm8 vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src,src2,aux
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,unit,vex_mpw,opcode>, vpshldd,4,VEX_66_0F3A_W0,71h, vpshldq,8,VEX_66_0F3A_W1,71h, \
|
||||
vpshrdd,4,VEX_66_0F3A_W0,73h, vpshrdq,8,VEX_66_0F3A_W1,73h
|
||||
|
||||
macro instr? dest*,src*,src2*,aux*&
|
||||
require AVX512_VBMI2
|
||||
AVX_512.basic_instruction_bcst_imm8 vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src,src2,aux
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,vex_mpw,opcode>, vpshldvw,VEX_66_0F38_W1,70h, vpshrdvw,VEX_66_0F38_W1,72h
|
||||
|
||||
macro instr? dest*,src*,src2*
|
||||
require AVX512_VBMI2
|
||||
AVX_512.basic_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src,src2
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,unit,vex_mpw,opcode>, vpshldvd,4,VEX_66_0F38_W0,71h, vpshldvq,8,VEX_66_0F38_W1,71h, \
|
||||
vpshrdvd,4,VEX_66_0F38_W0,73h, vpshrdvq,8,VEX_66_0F38_W1,73h
|
||||
|
||||
macro instr? dest*,src*,src2*
|
||||
require AVX512_VBMI2
|
||||
AVX_512.basic_instruction_bcst vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src,src2
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,vex_mpw,opcode>, vpcompressb,VEX_66_0F38_W0,63h, vpcompressw,VEX_66_0F38_W1,63h
|
||||
|
||||
macro instr? dest*,src*
|
||||
require AVX512_VBMI2
|
||||
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>, vpexpandb,VEX_66_0F38_W0,62h, vpexpandw,VEX_66_0F38_W1,62h
|
||||
|
||||
macro instr? dest*,src*
|
||||
require AVX512_VBMI2
|
||||
AVX_512.single_source_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src
|
||||
end macro
|
||||
|
||||
end iterate
|
122
toolchain/fasm2/include/iset/cet.inc
Normal file
122
toolchain/fasm2/include/iset/cet.inc
Normal file
@ -0,0 +1,122 @@
|
||||
|
||||
|
||||
iterate <instr,modrm>, endbr32,0FBh, endbr64,0FAh
|
||||
|
||||
macro instr?
|
||||
require CET_IBT
|
||||
db 0F3h,0Fh,1Eh,modrm
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext,postbyte>, clrssbsy,0AEh,6, rstorssp,01h,5
|
||||
|
||||
macro instr? src*
|
||||
require CET_SS
|
||||
x86.parse_operand@src src
|
||||
if @src.type = 'mem'
|
||||
if @src.size and not 8
|
||||
err 'invalid operand size'
|
||||
else
|
||||
@src.opcode_prefix = 0F3h
|
||||
x86.store_instruction@src <0Fh,ext>,postbyte
|
||||
end if
|
||||
else
|
||||
err 'invalid operand'
|
||||
end if
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext,postbyte>, incsspd,0AEh,5, rdsspd,1Eh,1
|
||||
|
||||
macro instr? src*
|
||||
require CET_SS
|
||||
x86.parse_operand@src src
|
||||
if @src.type = 'reg'
|
||||
if @src.size <> 4
|
||||
err 'invalid operand size'
|
||||
else
|
||||
@src.opcode_prefix = 0F3h
|
||||
x86.store_instruction@src <0Fh,ext>,postbyte
|
||||
end if
|
||||
else
|
||||
err 'invalid operand'
|
||||
end if
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext,postbyte>, incsspq,0AEh,5, rdsspq,1Eh,1
|
||||
|
||||
macro instr? src*
|
||||
require CET_SS
|
||||
x86.parse_operand@src src
|
||||
if @src.type = 'reg'
|
||||
if @src.size <> 8
|
||||
err 'invalid operand size'
|
||||
else
|
||||
x86.select_operand_prefix@src 8
|
||||
@src.opcode_prefix = 0F3h
|
||||
x86.store_instruction@src <0Fh,ext>,postbyte
|
||||
end if
|
||||
else
|
||||
err 'invalid operand'
|
||||
end if
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,modrm>, saveprevssp,0EAh, setssbsy,0E8h
|
||||
|
||||
macro instr?
|
||||
require CET_SS
|
||||
db 0F3h,0Fh,01h,modrm
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,prefix,ext>, wrssd,0,0F6h, wrussd,66h,0F5h
|
||||
|
||||
macro instr? dest*,src*
|
||||
require CET_SS
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
local size
|
||||
if @src.size <> 4
|
||||
err 'invalid operand size'
|
||||
else if @dest.size and not @src.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
if @src.type = 'reg' & ( @dest.type = 'reg' | @dest.type = 'mem' )
|
||||
@dest.opcode_prefix = prefix
|
||||
x86.store_instruction@dest <0Fh,38h,ext>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,prefix,ext>, wrssq,0,0F6h, wrussq,66h,0F5h
|
||||
|
||||
macro instr? dest*,src*
|
||||
require CET_SS
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
local size
|
||||
if @src.size <> 8
|
||||
err 'invalid operand size'
|
||||
else if @dest.size and not @src.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
if @src.type = 'reg' & ( @dest.type = 'reg' | @dest.type = 'mem' )
|
||||
x86.select_operand_prefix@dest 8
|
||||
@dest.opcode_prefix = prefix
|
||||
x86.store_instruction@dest <0Fh,38h,ext>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
end iterate
|
742
toolchain/fasm2/include/iset/fpu.inc
Normal file
742
toolchain/fasm2/include/iset/fpu.inc
Normal file
@ -0,0 +1,742 @@
|
||||
|
||||
element st?
|
||||
|
||||
repeat 8, i:0
|
||||
element st#i? : st? + i
|
||||
end repeat
|
||||
|
||||
iterate context, @dest,@src,@src2,@aux
|
||||
|
||||
namespace context
|
||||
|
||||
calminstruction x87.parse_operand#context operand
|
||||
|
||||
local i
|
||||
|
||||
match =st?(i), operand
|
||||
jyes indexed_streg_operand
|
||||
|
||||
call x86.parse_operand#context, operand
|
||||
|
||||
check type = 'imm' & size = 0
|
||||
jno done
|
||||
check imm eq 1 elementof imm & 1 metadataof imm relativeto st?
|
||||
jyes streg_operand
|
||||
check imm relativeto st? & imm = st?
|
||||
jno done
|
||||
|
||||
compute type, 'streg'
|
||||
compute mod, 11b
|
||||
compute rm, 0
|
||||
|
||||
exit
|
||||
|
||||
streg_operand:
|
||||
|
||||
compute type, 'streg'
|
||||
compute mod, 11b
|
||||
compute rm, 1 metadataof imm - st?
|
||||
|
||||
exit
|
||||
|
||||
indexed_streg_operand:
|
||||
|
||||
compute size, 0
|
||||
compute type, 'streg'
|
||||
compute mod, 11b
|
||||
compute rm, +i
|
||||
|
||||
done:
|
||||
|
||||
end calminstruction
|
||||
|
||||
end namespace
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,opcode>, fwait,9Bh, wait,9Bh
|
||||
|
||||
calminstruction instr?
|
||||
call x86.require.8087
|
||||
emit 1, opcode
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,byte1,byte2>, fnop,0D9h,0D0h, fchs,0D9h,0E0h, fabs,0D9h,0E1h, ftst,0D9h,0E4h, fxam,0D9h,0E5h, fld1,0D9h,0E8h, \
|
||||
fldl2t,0D9h,0E9h, fldl2e,0D9h,0EAh, fldpi,0D9h,0EBh, fldlg2,0D9h,0ECh, fldln2,0D9h,0EDh, fldz,0D9h,0EEh, \
|
||||
f2xm1,0D9h,0F0h, fyl2x,0D9h,0F1h, fptan,0D9h,0F2h, fpatan,0D9h,0F3h, fxtract,0D9h,0F4h, \
|
||||
fdecstp,0D9h,0F6h, fincstp,0D9h,0F7h, fprem,0D9h,0F8h, \
|
||||
fyl2xp1,0D9h,0F9h, fsqrt,0D9h,0FAh, frndint,0D9h,0FCh, fscale,0D9h,0FDh, \
|
||||
fneni,0DBh,0E0h, fndisi,0DBh,0E1h, fnclex,0DBh,0E2h, fninit,0DBh,0E3h, \
|
||||
fcompp,0DEh,0D9h
|
||||
|
||||
calminstruction instr?
|
||||
call x86.require.8087
|
||||
emit 1, byte1
|
||||
emit 1, byte2
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,opcode>, fneni,0E0h, fndisi,0E1h
|
||||
|
||||
calminstruction instr?
|
||||
call x86.requireexact.8087
|
||||
emit 1, 0DBh
|
||||
emit 1, opcode
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate op, eni, disi, clex, init
|
||||
calminstruction f#op?
|
||||
asm fwait?
|
||||
asm fn#op?
|
||||
end calminstruction
|
||||
end iterate
|
||||
|
||||
calminstruction fsetpm?
|
||||
call x86.requireexact.80287
|
||||
emit 1, 0DBh
|
||||
emit 1, 0E4h
|
||||
end calminstruction
|
||||
|
||||
iterate <instr,postbyte>, fadd,0, fmul,1, fsub,4, fsubr,5, fdiv,6, fdivr,7
|
||||
|
||||
calminstruction instr? operand&
|
||||
call x86.require.8087
|
||||
local dest, src
|
||||
match dest=,src, operand
|
||||
jyes st
|
||||
call x87.parse_operand@dest, operand
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_combination_of_operands
|
||||
check @dest.size = 4
|
||||
jyes mem_dword
|
||||
check @dest.size = 8
|
||||
jyes mem_qword
|
||||
check @dest.size
|
||||
jno unknown_size
|
||||
err 'invalid operand size'
|
||||
jump mem_dword
|
||||
unknown_size:
|
||||
err 'operand size not specified'
|
||||
mem_dword:
|
||||
xcall x86.store_instruction@dest, (0D8h),(postbyte)
|
||||
exit
|
||||
mem_qword:
|
||||
xcall x86.store_instruction@dest, (0DCh),(postbyte)
|
||||
exit
|
||||
st:
|
||||
call x87.parse_operand@dest, dest
|
||||
call x87.parse_operand@src, src
|
||||
check @dest.type = 'streg' & @src.type = 'streg'
|
||||
jno invalid_combination_of_operands
|
||||
check @dest.rm = 0
|
||||
jyes st0_sti
|
||||
check @src.rm = 0
|
||||
jyes sti_st0
|
||||
jump invalid_combination_of_operands
|
||||
st0_sti:
|
||||
emit 1, 0D8h
|
||||
emit 1, 11b shl 6 + postbyte shl 3 + @src.rm
|
||||
exit
|
||||
sti_st0:
|
||||
check postbyte >= 4
|
||||
jyes switched
|
||||
emit 1, 0DCh
|
||||
emit 1, 11b shl 6 + postbyte shl 3 + @dest.rm
|
||||
exit
|
||||
switched:
|
||||
emit 1, 0DCh
|
||||
emit 1, 11b shl 6 + (postbyte xor 1) shl 3 + @dest.rm
|
||||
exit
|
||||
invalid_combination_of_operands:
|
||||
err 'invalid combination of operands'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,postbyte>, faddp,0, fmulp,1, fsubrp,4, fsubp,5, fdivrp,6, fdivp,7
|
||||
|
||||
calminstruction instr? operand&
|
||||
call x86.require.8087
|
||||
local dest, src
|
||||
match , operand
|
||||
jyes default
|
||||
match dest=,src, operand
|
||||
jno invalid_combination_of_operands
|
||||
call x87.parse_operand@dest, dest
|
||||
call x87.parse_operand@src, src
|
||||
check @dest.type = 'streg' & @src.type = 'streg' & @src.rm = 0
|
||||
jyes ok
|
||||
invalid_combination_of_operands:
|
||||
err 'invalid combination of operands'
|
||||
exit
|
||||
default:
|
||||
compute @dest.rm, 1
|
||||
ok:
|
||||
emit 1, 0DEh
|
||||
emit 1, 11b shl 6 + postbyte shl 3 + @dest.rm
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,postbyte>, fcom,2, fcomp,3
|
||||
|
||||
calminstruction instr? src:st1
|
||||
call x86.require.8087
|
||||
call x87.parse_operand@src, src
|
||||
check @src.type = 'streg'
|
||||
jyes st
|
||||
check @src.type = 'mem'
|
||||
jno invalid_operand
|
||||
check @src.size = 4
|
||||
jyes mem_dword
|
||||
check @src.size = 8
|
||||
jyes mem_qword
|
||||
check @src.size
|
||||
jno unknown_size
|
||||
err 'invalid operand size'
|
||||
jump mem_dword
|
||||
unknown_size:
|
||||
err 'operand size not specified'
|
||||
mem_dword: st:
|
||||
xcall x86.store_instruction@src, (0D8h),(postbyte)
|
||||
exit
|
||||
mem_qword:
|
||||
xcall x86.store_instruction@src, (0DCh),(postbyte)
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,postbyte>, fiadd,0, fimul,1, ficom,2, ficomp,3, fisub,4, fisubr,5, fidiv,6, fidivr,7
|
||||
|
||||
calminstruction instr? src*
|
||||
call x86.require.8087
|
||||
call x87.parse_operand@src, src
|
||||
check @src.type = 'mem'
|
||||
jno invalid_operand
|
||||
check @src.size = 2
|
||||
jyes mem_word
|
||||
check @src.size = 4
|
||||
jyes mem_dword
|
||||
check @src.size
|
||||
jno unknown_size
|
||||
err 'invalid operand size'
|
||||
jump mem_word
|
||||
unknown_size:
|
||||
err 'operand size not specified'
|
||||
mem_word:
|
||||
xcall x86.store_instruction@src, (0DEh),(postbyte)
|
||||
exit
|
||||
mem_dword:
|
||||
xcall x86.store_instruction@src, (0DAh),(postbyte)
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
calminstruction fld? src*
|
||||
call x86.require.8087
|
||||
call x87.parse_operand@src, src
|
||||
check @src.type = 'streg'
|
||||
jyes st
|
||||
check @src.type = 'mem'
|
||||
jno invalid_operand
|
||||
check @src.size = 4
|
||||
jyes mem_dword
|
||||
check @src.size = 8
|
||||
jyes mem_qword
|
||||
check @src.size = 10
|
||||
jyes mem_tword
|
||||
check @src.size
|
||||
jno unknown_size
|
||||
err 'invalid operand size'
|
||||
jump mem_dword
|
||||
unknown_size:
|
||||
err 'operand size not specified'
|
||||
mem_dword: st:
|
||||
xcall x86.store_instruction@src, (0D9h),(0)
|
||||
exit
|
||||
mem_qword:
|
||||
xcall x86.store_instruction@src, (0DDh),(0)
|
||||
exit
|
||||
mem_tword:
|
||||
xcall x86.store_instruction@src, (0DBh),(5)
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
calminstruction fst? dest*
|
||||
call x86.require.8087
|
||||
call x87.parse_operand@dest, dest
|
||||
check @dest.type = 'streg'
|
||||
jyes st
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
check @dest.size = 4
|
||||
jyes mem_dword
|
||||
check @dest.size = 8
|
||||
jyes mem_qword
|
||||
check @dest.size
|
||||
jno unknown_size
|
||||
err 'invalid operand size'
|
||||
jump mem_dword
|
||||
unknown_size:
|
||||
err 'operand size not specified'
|
||||
mem_dword:
|
||||
xcall x86.store_instruction@dest, (0D9h),(2)
|
||||
exit
|
||||
mem_qword: st:
|
||||
xcall x86.store_instruction@dest, (0DDh),(2)
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
calminstruction fstp? dest*
|
||||
call x86.require.8087
|
||||
call x87.parse_operand@dest, dest
|
||||
check @dest.type = 'streg'
|
||||
jyes st
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
check @dest.size = 4
|
||||
jyes mem_dword
|
||||
check @dest.size = 8
|
||||
jyes mem_qword
|
||||
check @dest.size = 10
|
||||
jyes mem_tword
|
||||
check @dest.size
|
||||
jno unknown_size
|
||||
err 'invalid operand size'
|
||||
jump mem_dword
|
||||
unknown_size:
|
||||
err 'operand size not specified'
|
||||
mem_dword:
|
||||
xcall x86.store_instruction@dest, (0D9h),(3)
|
||||
exit
|
||||
mem_qword: st:
|
||||
xcall x86.store_instruction@dest, (0DDh),(3)
|
||||
exit
|
||||
mem_tword:
|
||||
xcall x86.store_instruction@dest, (0DBh),(7)
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
calminstruction fild? src*
|
||||
call x86.require.8087
|
||||
call x87.parse_operand@src, src
|
||||
check @src.type = 'mem'
|
||||
jno invalid_operand
|
||||
check @src.size = 2
|
||||
jyes mem_word
|
||||
check @src.size = 4
|
||||
jyes mem_dword
|
||||
check @src.size = 8
|
||||
jyes mem_qword
|
||||
check @src.size
|
||||
jno unknown_size
|
||||
err 'invalid operand size'
|
||||
jump mem_word
|
||||
unknown_size:
|
||||
err 'operand size not specified'
|
||||
mem_word:
|
||||
xcall x86.store_instruction@src, (0DFh),(0)
|
||||
exit
|
||||
mem_dword:
|
||||
xcall x86.store_instruction@src, (0DBh),(0)
|
||||
exit
|
||||
mem_qword:
|
||||
xcall x86.store_instruction@src, (0DFh),(5)
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
calminstruction fist? dest*
|
||||
call x86.require.8087
|
||||
call x87.parse_operand@dest, dest
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
check @dest.size = 2
|
||||
jyes mem_word
|
||||
check @dest.size = 4
|
||||
jyes mem_dword
|
||||
check @dest.size
|
||||
jno unknown_size
|
||||
err 'invalid operand size'
|
||||
jump mem_word
|
||||
unknown_size:
|
||||
err 'operand size not specified'
|
||||
mem_word:
|
||||
xcall x86.store_instruction@dest, (0DFh),(2)
|
||||
exit
|
||||
mem_dword:
|
||||
xcall x86.store_instruction@dest, (0DBh),(2)
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
calminstruction fistp? dest*
|
||||
call x86.require.8087
|
||||
call x87.parse_operand@dest, dest
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
check @dest.size = 2
|
||||
jyes mem_word
|
||||
check @dest.size = 4
|
||||
jyes mem_dword
|
||||
check @dest.size = 8
|
||||
jyes mem_qword
|
||||
check @dest.size
|
||||
jno unknown_size
|
||||
err 'invalid operand size'
|
||||
jump mem_word
|
||||
unknown_size:
|
||||
err 'operand size not specified'
|
||||
mem_word:
|
||||
xcall x86.store_instruction@dest, (0DFh),(3)
|
||||
exit
|
||||
mem_dword:
|
||||
xcall x86.store_instruction@dest, (0DBh),(3)
|
||||
exit
|
||||
mem_qword:
|
||||
xcall x86.store_instruction@dest, (0DFh),(7)
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
calminstruction fisttp? dest*
|
||||
call x86.require.8087
|
||||
call x87.parse_operand@dest, dest
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
check @dest.size = 2
|
||||
jyes mem_word
|
||||
check @dest.size = 4
|
||||
jyes mem_dword
|
||||
check @dest.size = 8
|
||||
jyes mem_qword
|
||||
check @dest.size
|
||||
jno unknown_size
|
||||
err 'invalid operand size'
|
||||
jump mem_word
|
||||
unknown_size:
|
||||
err 'operand size not specified'
|
||||
mem_word:
|
||||
xcall x86.store_instruction@dest, (0DFh),(1)
|
||||
exit
|
||||
mem_dword:
|
||||
xcall x86.store_instruction@dest, (0DBh),(1)
|
||||
exit
|
||||
mem_qword:
|
||||
xcall x86.store_instruction@dest, (0DDh),(1)
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
iterate <instr,postbyte>, fbld,4, fbstp,6
|
||||
|
||||
calminstruction instr? src*
|
||||
call x86.require.8087
|
||||
call x87.parse_operand@src, src
|
||||
check @src.type = 'mem'
|
||||
jno invalid_operand
|
||||
check @src.size and not 10
|
||||
jyes invalid_operand_size
|
||||
xcall x86.store_instruction@src, (0DFh),(postbyte)
|
||||
exit
|
||||
invalid_operand_size:
|
||||
err 'invalid operand size'
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
calminstruction fxch? src:st1
|
||||
call x86.require.8087
|
||||
call x87.parse_operand@src, src
|
||||
check @src.type = 'streg'
|
||||
jno invalid_operand
|
||||
emit 1, 0D9h
|
||||
emit 1, 11b shl 6 + 1 shl 3 + @src.rm
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
iterate <instr,basecode>, ffree,0DDh, ffreep,0DFh
|
||||
|
||||
calminstruction instr? src*
|
||||
call x86.require.8087
|
||||
call x87.parse_operand@src, src
|
||||
check @src.type = 'streg'
|
||||
jno invalid_operand
|
||||
emit 1, basecode
|
||||
emit 1, 11b shl 6 + @src.rm
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
calminstruction fnstsw? dest*
|
||||
call x86.require.8087
|
||||
call x86.parse_operand@dest, dest
|
||||
check @dest.size and not 2
|
||||
jyes invalid_operand_size
|
||||
check @dest.type = 'mem'
|
||||
jyes mem
|
||||
check @dest.type = 'reg' & @dest.rm = 0
|
||||
jno invalid_operand
|
||||
emit 1, 0DFh
|
||||
emit 1, 0E0h
|
||||
exit
|
||||
mem:
|
||||
xcall x86.store_instruction@dest, (0DDh),(7)
|
||||
exit
|
||||
invalid_operand_size:
|
||||
err 'invalid operand size'
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
iterate <instr,postbyte>, fldcw,5, fnstcw,7
|
||||
|
||||
calminstruction instr? dest*
|
||||
call x86.parse_operand@dest, dest
|
||||
check @dest.size and not 2
|
||||
jyes invalid_operand_size
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
xcall x86.store_instruction@dest, (0D9h),(postbyte)
|
||||
exit
|
||||
invalid_operand_size:
|
||||
err 'invalid operand size'
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,postbyte>, fldenv,4, fnstenv,6
|
||||
|
||||
calminstruction instr? dest*
|
||||
call x86.require.8087
|
||||
call x86.parse_operand@dest, dest
|
||||
check @dest.size and not 14
|
||||
jyes invalid_operand_size
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
xcall x86.store_instruction@dest, (0D9h),(postbyte)
|
||||
exit
|
||||
invalid_operand_size:
|
||||
err 'invalid operand size'
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,postbyte>, frstor,4, fnsave,6
|
||||
|
||||
calminstruction instr? dest*
|
||||
call x86.require.8087
|
||||
call x86.parse_operand@dest, dest
|
||||
check @dest.size and not 94
|
||||
jyes invalid_operand_size
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
xcall x86.store_instruction@dest, (0DDh),(postbyte)
|
||||
exit
|
||||
invalid_operand_size:
|
||||
err 'invalid operand size'
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate op, stsw, stcw, stenv, save
|
||||
calminstruction f#op? dest*
|
||||
asm fwait?
|
||||
asm fn#op? dest
|
||||
end calminstruction
|
||||
end iterate
|
||||
|
||||
iterate <instr,byte1,byte2>, fprem1,0D9h,0F5h, fsincos,0D9h,0FBh, fsin,0D9h,0FEh, fcos,0D9h,0FFh, fucompp,0DAh,0E9h
|
||||
|
||||
calminstruction instr?
|
||||
call x86.require.80387
|
||||
emit 1, byte1
|
||||
emit 1, byte2
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,postbyte>, fucom,4, fucomp,5
|
||||
|
||||
calminstruction instr? src:st1
|
||||
call x86.require.80387
|
||||
call x87.parse_operand@src, src
|
||||
check @src.type = 'streg'
|
||||
jno invalid_operand
|
||||
xcall x86.store_instruction@src, (0DDh),(postbyte)
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
|
||||
iterate <instr,postbyte>, fldenv,4, fnstenv,6
|
||||
|
||||
calminstruction instr? dest*
|
||||
call x86.require.80387
|
||||
call x86.parse_operand@dest, dest
|
||||
check @dest.size & ( ( x86.mode = 16 & @dest.size <> 14 ) | ( x86.mode = 32 & @dest.size <> 28 ) )
|
||||
jyes invalid_operand_size
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
xcall x86.store_instruction@dest, (0D9h),(postbyte)
|
||||
exit
|
||||
invalid_operand_size:
|
||||
err 'invalid operand size'
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,postbyte>, fldenvw,4, fnstenvw,6
|
||||
|
||||
calminstruction instr? dest*
|
||||
call x86.require.80387
|
||||
call x86.parse_operand@dest, dest
|
||||
check @dest.size and not 14
|
||||
jyes invalid_operand_size
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
xcall x86.store_operand_prefix, (2)
|
||||
xcall x86.store_instruction@dest, (0D9h),(postbyte)
|
||||
exit
|
||||
invalid_operand_size:
|
||||
err 'invalid operand size'
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,postbyte>, fldenvd,4, fnstenvd,6
|
||||
|
||||
calminstruction instr? dest*
|
||||
call x86.require.80387
|
||||
call x86.parse_operand@dest, dest
|
||||
check @dest.size and not 28
|
||||
jyes invalid_operand_size
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
xcall x86.store_operand_prefix, (4)
|
||||
xcall x86.store_instruction@dest, (0D9h),(postbyte)
|
||||
exit
|
||||
invalid_operand_size:
|
||||
err 'invalid operand size'
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,postbyte>, frstor,4, fnsave,6
|
||||
|
||||
calminstruction instr? dest*
|
||||
call x86.require.80387
|
||||
call x86.parse_operand@dest, dest
|
||||
check @dest.size & ( ( x86.mode = 16 & @dest.size <> 94 ) | ( x86.mode = 32 & @dest.size <> 108 ) )
|
||||
jyes invalid_operand_size
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
xcall x86.store_instruction@dest, (0DDh),(postbyte)
|
||||
exit
|
||||
invalid_operand_size:
|
||||
err 'invalid operand size'
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,postbyte>, frstorw,4, fnsavew,6
|
||||
|
||||
calminstruction instr? dest*
|
||||
call x86.require.80387
|
||||
call x86.parse_operand@dest, dest
|
||||
check @dest.size and not 94
|
||||
jyes invalid_operand_size
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
xcall x86.store_operand_prefix, (2)
|
||||
xcall x86.store_instruction@dest, (0DDh),(postbyte)
|
||||
exit
|
||||
invalid_operand_size:
|
||||
err 'invalid operand size'
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,postbyte>, frstord,4, fnsaved,6
|
||||
calminstruction instr? dest*
|
||||
call x86.require.80387
|
||||
call x86.parse_operand@dest, dest
|
||||
check @dest.size and not 108
|
||||
jyes invalid_operand_size
|
||||
check @dest.type = 'mem'
|
||||
jno invalid_operand
|
||||
xcall x86.store_operand_prefix, (4)
|
||||
xcall x86.store_instruction@dest, (0DDh),(postbyte)
|
||||
exit
|
||||
invalid_operand_size:
|
||||
err 'invalid operand size'
|
||||
exit
|
||||
invalid_operand:
|
||||
err 'invalid operand'
|
||||
end calminstruction
|
||||
|
||||
end iterate
|
||||
|
||||
iterate op, stenvw, stenvd, savew, saved
|
||||
calminstruction f#op? dest*
|
||||
asm fwait?
|
||||
asm fn#op? dest
|
||||
end calminstruction
|
||||
end iterate
|
33
toolchain/fasm2/include/iset/gfni.inc
Normal file
33
toolchain/fasm2/include/iset/gfni.inc
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
iterate <instr,supp>, gf2p8mulb,0CFh
|
||||
macro instr? dest*,src*
|
||||
require GFNI
|
||||
SSE.basic_instruction 66h,<38h,supp>,16,dest,src
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,supp>, gf2p8affineinvqb,0CFh, gf2p8affineqb,0CEh
|
||||
macro instr? dest*,src*,imm*
|
||||
require GFNI
|
||||
SSE.basic_instruction_imm8 66h,<3Ah,supp>,16,dest,src,imm
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,opcode>, gf2p8mulb,0CFh
|
||||
|
||||
macro v#instr? dest*,src*,src2*&
|
||||
require GFNI
|
||||
AVX_512.basic_instruction VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,0,dest,src,src2
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
iterate <instr,opcode>, gf2p8affineinvqb,0CFh, gf2p8affineqb,0CEh
|
||||
|
||||
macro v#instr? dest*,src*,src2*,imm*&
|
||||
require GFNI
|
||||
AVX_512.basic_instruction_bcst_imm8 VEX_66_0F3A_W1,EVEX_W1+EVEX_VL,opcode,8,dest,src,src2,imm
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
164
toolchain/fasm2/include/iset/mmx.inc
Normal file
164
toolchain/fasm2/include/iset/mmx.inc
Normal file
@ -0,0 +1,164 @@
|
||||
|
||||
element MMX.reg
|
||||
|
||||
repeat 8, i:0
|
||||
element mm#i? : MMX.reg + i
|
||||
end repeat
|
||||
|
||||
iterate context, @dest,@src,@src2,@aux
|
||||
|
||||
namespace context
|
||||
|
||||
calminstruction MMX.parse_operand#context operand
|
||||
|
||||
call x86.parse_operand#context, operand
|
||||
|
||||
check type = 'imm' & size = 0
|
||||
jno done
|
||||
check imm eq 1 elementof imm & 1 metadataof imm relativeto MMX.reg
|
||||
jno done
|
||||
|
||||
compute type, 'mmreg'
|
||||
compute mod, 11b
|
||||
compute rm, 1 metadataof imm - MMX.reg
|
||||
compute size, 8
|
||||
|
||||
done:
|
||||
|
||||
end calminstruction
|
||||
|
||||
calminstruction MMX.select_operand_prefix#context size*
|
||||
check size = 16
|
||||
jno no_prefix
|
||||
call x86.require.SSE2
|
||||
compute prefix, 66h
|
||||
exit
|
||||
no_prefix:
|
||||
check size <> 8
|
||||
jno done
|
||||
err 'invalid operand size'
|
||||
done:
|
||||
end calminstruction
|
||||
|
||||
end namespace
|
||||
|
||||
end iterate
|
||||
|
||||
calminstruction MMX.basic_instruction ext,dest,src
|
||||
call x86.require.MMX
|
||||
call SSE.parse_operand@dest, dest
|
||||
call SSE.parse_operand@src, src
|
||||
check @src.size and not @dest.size
|
||||
jno size_ok
|
||||
err 'operand sizes do not match'
|
||||
size_ok:
|
||||
check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
jno invalid_combination_of_operands
|
||||
call MMX.select_operand_prefix@src, @dest.size
|
||||
xcall x86.store_instruction@src, <0Fh,ext>,@dest.rm
|
||||
exit
|
||||
invalid_combination_of_operands:
|
||||
err 'invalid combination of operands'
|
||||
end calminstruction
|
||||
|
||||
calminstruction MMX.bit_shift_instruction ext,dest,src
|
||||
call x86.require.MMX
|
||||
call SSE.parse_operand@dest, dest
|
||||
call SSE.parse_operand@src, src
|
||||
check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
jyes mmreg_rm
|
||||
check @dest.type = 'mmreg' & @src.type = 'imm'
|
||||
jyes mmreg_imm
|
||||
err 'invalid combination of operands'
|
||||
exit
|
||||
mmreg_rm:
|
||||
check @src.size and not @dest.size
|
||||
jno mmreg_rm_ok
|
||||
err 'operand sizes do not match'
|
||||
mmreg_rm_ok:
|
||||
call MMX.select_operand_prefix@src, @dest.size
|
||||
xcall x86.store_instruction@src, <0Fh,ext>,@dest.rm
|
||||
exit
|
||||
mmreg_imm:
|
||||
check @src.size and not 1
|
||||
jno rm_mmreg_ok
|
||||
err 'invalid operand size'
|
||||
rm_mmreg_ok:
|
||||
local iext, irm
|
||||
compute iext, 70h+(ext and 0Fh)
|
||||
compute irm, ((ext shr 4)-0Ch) shl 1
|
||||
call MMX.select_operand_prefix@dest, @dest.size
|
||||
xcall x86.store_instruction@dest, <0Fh,iext>,irm,byte,@src.imm
|
||||
end calminstruction
|
||||
|
||||
iterate <instr,opcode>, punpcklbw,60h, punpcklwd,61h, punpckldq,62h, packsswb,63h, pcmpgtb,64h, pcmpgtw,65h, pcmpgtd,66h, packuswb,67h, punpckhbw,68h, \
|
||||
punpckhwd,69h, punpckhdq,6Ah, packssdw,6Bh, pcmpeqb,74h, pcmpeqw,75h, pcmpeqd,76h, pmullw,0D5h, psubusb,0D8h, psubusw,0D9h, \
|
||||
pand,0DBh, paddusb,0DCh, paddusw,0DDh, pandn,0DFh, pmulhw,0E5h, psubsb,0E8h, psubsw,0E9h, por,0EBh, paddsb,0ECh, paddsw,0EDh, \
|
||||
pxor,0EFh, pmaddwd,0F5h, psubb,0F8h, psubw,0F9h, psubd,0FAh, paddb,0FCh, paddw,0FDh, paddd,0FEh
|
||||
|
||||
macro instr? dest*,src*
|
||||
MMX.basic_instruction opcode,dest,src
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
calminstruction movq? dest*,src*
|
||||
call x86.require.MMX
|
||||
call MMX.parse_operand@dest, dest
|
||||
call MMX.parse_operand@src, src
|
||||
check (@src.size or @dest.size) and not 8
|
||||
jno size_ok
|
||||
err 'invalid operand size'
|
||||
size_ok:
|
||||
check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
jyes mmreg_mem
|
||||
check @dest.type = 'mem' & @src.type = 'mmreg'
|
||||
jyes mem_mmreg
|
||||
err 'invalid combination of operands'
|
||||
exit
|
||||
mmreg_mem:
|
||||
xcall x86.store_instruction@src, <0Fh,6Fh>,@dest.rm
|
||||
exit
|
||||
mem_mmreg:
|
||||
xcall x86.store_instruction@dest, <0Fh,7Fh>,@src.rm
|
||||
exit
|
||||
end calminstruction
|
||||
|
||||
calminstruction movd? dest*,src*
|
||||
call x86.require.MMX
|
||||
call MMX.parse_operand@dest, dest
|
||||
call MMX.parse_operand@src, src
|
||||
check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'reg')
|
||||
jyes mmreg_rm
|
||||
check (@dest.type = 'mem' | @dest.type = 'reg') & @src.type = 'mmreg'
|
||||
jyes rm_mmreg
|
||||
err 'invalid combination of operands'
|
||||
exit
|
||||
mmreg_rm:
|
||||
check @src.size and not 4
|
||||
jno mmreg_rm_ok
|
||||
err 'invalid operand size'
|
||||
mmreg_rm_ok:
|
||||
xcall x86.store_instruction@src, <0Fh,6Eh>,@dest.rm
|
||||
exit
|
||||
rm_mmreg:
|
||||
check @dest.size and not 4
|
||||
jno rm_mmreg_ok
|
||||
err 'invalid operand size'
|
||||
rm_mmreg_ok:
|
||||
xcall x86.store_instruction@dest, <0Fh,7Eh>,@src.rm
|
||||
end calminstruction
|
||||
|
||||
iterate <instr,opcode>, psrlw,0D1h, psrld,0D2h, psrlq,0D3h, psrad,0E2h, psraw,0E1h, psllw,0F1h, pslld,0F2h, psllq,0F3h
|
||||
|
||||
macro instr? dest*,src*
|
||||
MMX.bit_shift_instruction opcode,dest,src
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
calminstruction emms?
|
||||
call x86.require.MMX
|
||||
emit 1, 0Fh
|
||||
emit 1, 77h
|
||||
end calminstruction
|
194
toolchain/fasm2/include/iset/mpx.inc
Normal file
194
toolchain/fasm2/include/iset/mpx.inc
Normal file
@ -0,0 +1,194 @@
|
||||
|
||||
element MPX.bnd
|
||||
|
||||
repeat 4, i:0
|
||||
element bnd#i? : MPX.bnd + i
|
||||
end repeat
|
||||
|
||||
macro MPX.parse_operand ns,op
|
||||
x86.parse_operand#ns op
|
||||
if ns.type = 'imm' & ns.size = 0 & ns.imm eq 1 elementof ns.imm & 1 metadataof ns.imm relativeto MPX.bnd
|
||||
ns.type = 'bnd'
|
||||
ns.mod = 11b
|
||||
ns.rm = 1 metadataof ns.imm - MPX.bnd
|
||||
ns.size = 0
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro MPX.parse_sib_operand ns,op&
|
||||
match [b=,si], op
|
||||
ns.split = 1
|
||||
ns.segment_prefix = 0
|
||||
ns.prefix = 0
|
||||
ns.opcode_prefix = 0
|
||||
ns.rex_prefix = 0
|
||||
ns.size = 0
|
||||
ns.type = 'mem'
|
||||
ns.base_part = +b
|
||||
ns.index_part = +si
|
||||
if x86.mode = 64
|
||||
ns.mode = 64
|
||||
ns.address_registers_type = x86.r64
|
||||
else
|
||||
ns.mode = 32
|
||||
ns.address_registers_type = x86.r32
|
||||
end if
|
||||
ns.base_registers = 0
|
||||
ns.index_registers = 0
|
||||
repeat elementsof ns.base_part
|
||||
if % metadataof ns.base_part relativeto x86.r16 | % metadataof ns.base_part relativeto x86.r32 | % metadataof ns.base_part relativeto x86.r64 | % metadataof ns.address relativeto x86.ip
|
||||
ns.base_registers = ns.base_registers + % elementof ns.base_part * % scaleof ns.base_part
|
||||
end if
|
||||
end repeat
|
||||
repeat elementsof ns.index_part
|
||||
if % metadataof ns.index_part relativeto x86.r16 | % metadataof ns.index_part relativeto x86.r32 | % metadataof ns.index_part relativeto x86.r64 | % metadataof ns.address relativeto x86.ip
|
||||
ns.index_registers = ns.index_registers + % elementof ns.index_part * % scaleof ns.index_part
|
||||
end if
|
||||
end repeat
|
||||
ns.displacement = ns.base_part - ns.base_registers + ns.index_part - ns.index_registers
|
||||
if ns.index_registers eq 0
|
||||
ns.index = 4
|
||||
ns.scale = 1
|
||||
else if elementsof ns.index_registers = 1 & 1 metadataof ns.index_registers relativeto ns.address_registers_type & 1 metadataof ns.index_registers - ns.address_registers_type <> 4
|
||||
ns.index = 1 metadataof ns.index_registers - ns.address_registers_type
|
||||
ns.scale = 1 scaleof ns.index_registers
|
||||
else
|
||||
err 'invalid address'
|
||||
end if
|
||||
if ns.base_registers eq 0
|
||||
ns.rm = 4
|
||||
ns.base = 5
|
||||
ns.index_only = 1
|
||||
else if ns.base_registers eq 1 elementof ns.base_registers & 1 metadataof ns.base_registers relativeto ns.address_registers_type
|
||||
ns.base = 1 metadataof ns.base_registers - ns.address_registers_type
|
||||
if ns.index = 4 & ns.base <> 4
|
||||
ns.rm = ns.base
|
||||
else
|
||||
ns.rm = 4
|
||||
end if
|
||||
ns.index_only = 0
|
||||
else
|
||||
err 'invalid address'
|
||||
end if
|
||||
ns.auto_relative = 0
|
||||
ns.displacement_size = 4
|
||||
ns.mod = 2
|
||||
if ns.index_only
|
||||
ns.mod = 0
|
||||
else if ns.displacement relativeto 0
|
||||
if ns.displacement = 0 & ns.rm and 111b <> 5 & (ns.rm <> 4 | ns.base and 111b <> 5)
|
||||
ns.displacement_size = 0
|
||||
ns.mod = 0
|
||||
else if ns.displacement < 80h & ns.displacement >= -80h
|
||||
ns.displacement_size = 1
|
||||
ns.mod = 1
|
||||
else if ns.displacement - 1 shl ns.mode >= -80h & ns.displacement < 1 shl ns.mode
|
||||
ns.displacement = ns.displacement - 1 shl ns.mode
|
||||
ns.displacement_size = 1
|
||||
ns.mod = 1
|
||||
end if
|
||||
end if
|
||||
else
|
||||
ns.split = 0
|
||||
x86.parse_operand#ns op
|
||||
end match
|
||||
end macro
|
||||
|
||||
macro bndmk? dest*,src*&
|
||||
require MPX
|
||||
MPX.parse_operand @dest,dest
|
||||
MPX.parse_sib_operand @src,src
|
||||
if @dest.type = 'bnd' & @src.type = 'mem'
|
||||
if @src.split & ~ 0 scaleof @src.base_part eq 0
|
||||
err 'invalid base address'
|
||||
end if
|
||||
if (x86.mode = 64 & @src.size and not 8) | (x86.mode < 64 & @src.size and not 4)
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 0F3h
|
||||
x86.store_instruction@src <0Fh,1Bh>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro bndmov? dest*,src*
|
||||
require MPX
|
||||
MPX.parse_operand @dest,dest
|
||||
MPX.parse_operand @src,src
|
||||
if @dest.type = 'bnd' & (@src.type = 'bnd' | @src.type = 'mem')
|
||||
if (x86.mode = 64 & @src.size and not 16) | (x86.mode < 64 & @src.size and not 8)
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if @src.type = 'mem' & @src.mode <> x86.mode
|
||||
err 'invalid address'
|
||||
end if
|
||||
@src.opcode_prefix = 66h
|
||||
x86.store_instruction@src <0Fh,1Ah>,@dest.rm
|
||||
else if @dest.type = 'mem' & @src.type = 'bnd'
|
||||
if (x86.mode = 64 & @dest.size and not 16) | (x86.mode < 64 & @dest.size and not 8)
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if @dest.type = 'mem' & @dest.mode <> x86.mode
|
||||
err 'invalid address'
|
||||
end if
|
||||
@dest.opcode_prefix = 66h
|
||||
x86.store_instruction@dest <0Fh,1Bh>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
iterate <instr,prefix,ext>, bndcl,0F3h,1Ah, bndcu,0F2h,1Ah, bndcn,0F2h,1Bh
|
||||
|
||||
macro instr? dest*,src*
|
||||
require MPX
|
||||
MPX.parse_operand @dest,dest
|
||||
x86.parse_operand @src,src
|
||||
if @dest.type = 'bnd' & (@src.type = 'reg' | @src.type = 'mem')
|
||||
if (x86.mode = 64 & @src.size and not 8) | (x86.mode < 64 & @src.size and not 4)
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if @src.type = 'mem' & @src.mode <> x86.mode
|
||||
err 'invalid address'
|
||||
end if
|
||||
@src.opcode_prefix = prefix
|
||||
x86.store_instruction@src <0Fh,ext>,@dest.rm
|
||||
else
|
||||
err 'invalid operand'
|
||||
end if
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
macro bndldx? dest*,src*&
|
||||
require MPX
|
||||
MPX.parse_operand @dest,dest
|
||||
MPX.parse_sib_operand @src,src
|
||||
if @dest.type = 'bnd' & @src.type = 'mem'
|
||||
if @src.scale > 1 | ( @src.split & ~ 0 scaleof @src.index_part eq 0 )
|
||||
err 'invalid index'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,1Ah>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro bndstx? operands*&
|
||||
require MPX
|
||||
match [dest] =, src, operands
|
||||
MPX.parse_sib_operand @dest,[dest]
|
||||
MPX.parse_operand @src,src
|
||||
if @dest.type = 'mem' & @src.type = 'bnd'
|
||||
if @dest.scale > 1 | ( @dest.split & ~ 0 scaleof @dest.index_part eq 0 )
|
||||
err 'invalid index'
|
||||
end if
|
||||
x86.store_instruction@dest <0Fh,1Bh>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end match
|
||||
end macro
|
24
toolchain/fasm2/include/iset/pclmulqdq.inc
Normal file
24
toolchain/fasm2/include/iset/pclmulqdq.inc
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
macro pclmulqdq? dest*,src*,imm*
|
||||
require PCLMULQDQ
|
||||
SSE.basic_instruction_imm8 66h,<3Ah,44h>,16,dest,src,imm
|
||||
end macro
|
||||
|
||||
macro vpclmulqdq? dest*,src*,src2*,aux*
|
||||
require VPCLMULQDQ
|
||||
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 = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm'
|
||||
if @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
else if @dest.size <> @src.size | @src2.size and not @dest.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
@src2.memsize = 0
|
||||
AVX_512.store_instruction@src2 @dest.size,VEX_66_0F3A_W0,EVEX_AS_VEX+EVEX_VL,44h,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
444
toolchain/fasm2/include/iset/sse.inc
Normal file
444
toolchain/fasm2/include/iset/sse.inc
Normal file
@ -0,0 +1,444 @@
|
||||
|
||||
element SSE.reg
|
||||
|
||||
repeat 16, i:0
|
||||
element xmm#i? : SSE.reg + i
|
||||
end repeat
|
||||
|
||||
iterate context, @dest,@src,@src2,@aux
|
||||
|
||||
namespace context
|
||||
|
||||
calminstruction SSE.parse_operand#context operand
|
||||
|
||||
call x86.parse_operand#context, operand
|
||||
|
||||
check type = 'imm' & size = 0
|
||||
jno done
|
||||
check imm eq 1 elementof imm & 1 metadataof imm relativeto MMX.reg
|
||||
jyes mm_register
|
||||
check imm eq 1 elementof imm & 1 metadataof imm relativeto SSE.reg
|
||||
jyes xmm_register
|
||||
exit
|
||||
|
||||
mm_register:
|
||||
|
||||
compute rm, 1 metadataof imm - MMX.reg
|
||||
compute size, 8
|
||||
|
||||
jump export_mmreg
|
||||
|
||||
xmm_register:
|
||||
|
||||
compute rm, 1 metadataof imm - SSE.reg
|
||||
compute size, 16
|
||||
|
||||
export_mmreg:
|
||||
|
||||
compute type, 'mmreg'
|
||||
compute mod, 11b
|
||||
|
||||
done:
|
||||
|
||||
end calminstruction
|
||||
|
||||
end namespace
|
||||
|
||||
end iterate
|
||||
|
||||
calminstruction SSE.basic_instruction pre,ext,msize,dest,src
|
||||
call x86.require.SSE
|
||||
call SSE.parse_operand@dest, dest
|
||||
call SSE.parse_operand@src, src
|
||||
check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
jno invalid_combination_of_operands
|
||||
check @dest.size <> 16 | (@src.type = 'mem' & @src.size and not msize) | (@src.type = 'mmreg' & @src.size <> 16)
|
||||
jno size_ok
|
||||
err 'invalid operand size'
|
||||
size_ok:
|
||||
compute @src.opcode_prefix, pre
|
||||
xcall x86.store_instruction@src, <0Fh,ext>,@dest.rm
|
||||
exit
|
||||
invalid_combination_of_operands:
|
||||
err 'invalid combination of operands'
|
||||
end calminstruction
|
||||
|
||||
calminstruction SSE.basic_instruction_imm8 pre,ext,msize,dest,src,aux
|
||||
call x86.require.SSE
|
||||
call SSE.parse_operand@dest, dest
|
||||
call SSE.parse_operand@src, src
|
||||
call x86.parse_operand@aux, aux
|
||||
check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm'
|
||||
jno invalid_combination_of_operands
|
||||
check @dest.size <> 16 | (@src.type = 'mem' & @src.size and not msize) | (@src.type = 'mmreg' & @src.size <> 16) | @aux.size and not 1
|
||||
jno size_ok
|
||||
err 'invalid operand size'
|
||||
size_ok:
|
||||
compute @src.opcode_prefix, pre
|
||||
xcall x86.store_instruction@src, <0Fh,ext>,@dest.rm,byte,@aux.imm
|
||||
exit
|
||||
invalid_combination_of_operands:
|
||||
err 'invalid combination of operands'
|
||||
end calminstruction
|
||||
|
||||
iterate <instr,ext>, sqrt,51h, rsqrt,52h, rcp,53h, add,58h, mul,59h, sub,5Ch, min,5Dh, div,5Eh, max,5Fh
|
||||
macro instr#ps? dest*,src*
|
||||
SSE.basic_instruction 0,ext,16,dest,src
|
||||
end macro
|
||||
macro instr#ss? dest*,src*
|
||||
SSE.basic_instruction 0F3h,ext,4,dest,src
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext>, and,54h, andn,55h, or,56h, xor,57h, unpckl,14h, unpckh,15h
|
||||
macro instr#ps? dest*,src*
|
||||
SSE.basic_instruction 0,ext,16,dest,src
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro cmpps? dest*,src*,code*
|
||||
SSE.basic_instruction_imm8 0,0C2h,16,dest,src,code
|
||||
end macro
|
||||
|
||||
macro cmpss? dest*,src*,code*
|
||||
SSE.basic_instruction_imm8 0F3h,0C2h,4,dest,src,code
|
||||
end macro
|
||||
|
||||
iterate <cond,code>, eq,0, lt,1, le,2, unord,3, neq,4, nlt,5, nle,6, ord,7
|
||||
macro cmp#cond#ps? dest*,src*
|
||||
cmpps dest,src,code
|
||||
end macro
|
||||
macro cmp#cond#ss? dest*,src*
|
||||
cmpss dest,src,code
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro shufps? dest*,src*,imm*
|
||||
SSE.basic_instruction_imm8 0,0C6h,16,dest,src,imm
|
||||
end macro
|
||||
|
||||
iterate <instr,ext>, movaps,28h, movups,10h
|
||||
macro instr? dest*,src*
|
||||
require SSE+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if (@dest.size or @src.size) and not 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
x86.store_instruction@src <0Fh,ext>,@dest.rm
|
||||
else if @dest.type = 'mem' & @src.type = 'mmreg'
|
||||
x86.store_instruction@dest <0Fh,ext+1>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext>, movlps,12h, movhps,16h
|
||||
macro instr? dest*,src*
|
||||
require SSE+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & @src.type = 'mem'
|
||||
if @dest.size <> 16 | @src.size and not 8
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,ext>,@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
|
||||
x86.store_instruction@dest <0Fh,ext+1>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext>, movhlps,12h, movlhps,16h
|
||||
macro instr? dest*,src*
|
||||
require SSE+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if (@dest.size or @src.size) and not 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if @dest.type = 'mmreg' & @src.type = 'mmreg'
|
||||
x86.store_instruction@src <0Fh,ext>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro movss? dest*,src*
|
||||
require SSE+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
if @dest.size <> 16 | (@src.type = 'mem' & @src.size and not 4) | (@src.type = 'mmreg' & @src.size <> 16)
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 0F3h
|
||||
x86.store_instruction@src <0Fh,10h>,@dest.rm
|
||||
else if @dest.type = 'mem' & @src.type = 'mmreg'
|
||||
if @dest.size and not 4 | @src.size <> 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@dest.opcode_prefix = 0F3h
|
||||
x86.store_instruction@dest <0Fh,11h>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro movntps? dest*,src*
|
||||
require SSE+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mem' & @src.type = 'mmreg'
|
||||
if (@dest.size or @src.size) and not 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@dest <0Fh,2Bh>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro movmskps? dest*,src*
|
||||
require SSE+
|
||||
x86.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'reg' & @src.type = 'mmreg'
|
||||
if (@dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8)) | @src.size <> 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,50h>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
iterate <instr,ext>, ucomiss,2Eh, comiss,2Fh
|
||||
macro instr? dest*,src*
|
||||
require SSE+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
if @dest.size <> 16 | (@src.type = 'mem' & @src.size and not 4) | (@src.type = 'mmreg' & @src.size <> 16)
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,ext>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro cvtpi2ps? dest*,src*
|
||||
require SSE+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
if @dest.size <> 16 | @src.size and not 8
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,2Ah>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro cvtsi2ss? dest*,src*
|
||||
require SSE+
|
||||
SSE.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'reg')
|
||||
if @src.size = 0
|
||||
err 'operand size not specified'
|
||||
else if @dest.size <> 16 | @src.size < 4
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.select_operand_prefix@src @src.size
|
||||
@src.opcode_prefix = 0F3h
|
||||
x86.store_instruction@src <0Fh,2Ah>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
iterate <instr,ext>, cvttps2pi,2Ch, cvtps2pi,2Dh
|
||||
macro instr? dest*,src*
|
||||
require SSE+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
if @dest.size <> 8 | (@src.size = 'mem' & @src.size and not 8) | (@src.size = 'mmreg' & @src.size <> 16)
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,ext>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext>, cvttss2si,2Ch, cvtss2si,2Dh
|
||||
macro instr? dest*,src*
|
||||
require SSE+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
if @dest.size < 4 | (@src.size = 'mem' & @src.size and not 4) | (@src.size = 'mmreg' & @src.size <> 16)
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.select_operand_prefix@src @dest.size
|
||||
@src.opcode_prefix = 0F3h
|
||||
x86.store_instruction@src <0Fh,ext>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext>, pminub,0DAh, pmaxub,0DEh, pavgb,0E0h, pavgw,0E3h, pmulhuw,0E4h, pminsw,0EAh, pmaxsw,0EEh, psadbw,0F6h
|
||||
macro instr? dest*,src*
|
||||
require SSE+
|
||||
MMX.basic_instruction ext,dest,src
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro pinsrw? dest*,src*,sel*
|
||||
require SSE+
|
||||
MMX.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if @dest.type = 'mmreg' & (@src.type = 'reg' | @src.type = 'mem') & @aux.type = 'imm'
|
||||
if (@src.type = 'reg' & @src.size <> 4) | (@src.type = 'mem' & @src.size and not 2) | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,0C4h>,@dest.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro pextrw? dest*,src*,sel*
|
||||
require SSE+
|
||||
x86.parse_operand@dest dest
|
||||
MMX.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if @dest.type = 'reg' & @src.type = 'mmreg' & @aux.type = 'imm'
|
||||
if @dest.size <> 4 | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,0C5h>,@dest.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro pshufw? dest*,src*,sel*
|
||||
require SSE+
|
||||
MMX.parse_operand@dest dest
|
||||
MMX.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm'
|
||||
if @src.size and not 8 | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,70h>,@dest.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro pmovmskb? dest*,src*
|
||||
require SSE+
|
||||
x86.parse_operand@dest dest
|
||||
MMX.parse_operand@src src
|
||||
if @dest.type = 'reg' & @src.type = 'mmreg'
|
||||
if @dest.size <> 4
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,0D7h>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro movntq? dest*,src*
|
||||
require SSE+
|
||||
MMX.parse_operand@dest dest
|
||||
MMX.parse_operand@src src
|
||||
if @dest.type = 'mem' & @src.type = 'mmreg'
|
||||
if @dest.size and not 8
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@dest <0Fh,0E7h>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro maskmovq? src*,sel*
|
||||
require SSE+
|
||||
MMX.parse_operand@src src
|
||||
MMX.parse_operand@aux sel
|
||||
if @src.type = 'mmreg' & @aux.type = 'mmreg'
|
||||
x86.store_instruction@aux <0Fh,0F7h>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
iterate <instr,postbyte>, prefetchnta,0, prefetcht0,1, prefetcht1,2, prefetcht2,3
|
||||
macro instr? src*
|
||||
require SSE+
|
||||
x86.parse_operand@src src
|
||||
if @src.type = 'mem'
|
||||
if @src.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,18h>,postbyte
|
||||
else
|
||||
err 'invalid operand'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro sfence?
|
||||
db 0Fh,0AEh,0F8h
|
||||
end macro
|
||||
|
||||
iterate <instr,postbyte>, fxsave,0, fxrstor,1
|
||||
macro instr? src*
|
||||
require SSE+
|
||||
x86.parse_operand@src src
|
||||
if @src.type = 'mem'
|
||||
if @src.size and not 512
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,0AEh>,postbyte
|
||||
else
|
||||
err 'invalid operand'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,postbyte>, ldmxcsr,2, stmxcsr,3
|
||||
macro instr? src*
|
||||
require SSE+
|
||||
x86.parse_operand@src src
|
||||
if @src.type = 'mem'
|
||||
if @src.size and not 4
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,0AEh>,postbyte
|
||||
else
|
||||
err 'invalid operand'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
579
toolchain/fasm2/include/iset/sse2.inc
Normal file
579
toolchain/fasm2/include/iset/sse2.inc
Normal file
@ -0,0 +1,579 @@
|
||||
|
||||
iterate <instr,ext>, sqrt,51h, rsqrt,52h, rcp,53h, add,58h, mul,59h, sub,5Ch, min,5Dh, div,5Eh, max,5Fh
|
||||
macro instr#pd? dest*,src*
|
||||
require SSE2+
|
||||
SSE.basic_instruction 66h,ext,16,dest,src
|
||||
end macro
|
||||
macro instr#sd? dest*,src*
|
||||
require SSE2+
|
||||
SSE.basic_instruction 0F2h,ext,8,dest,src
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext>, and,54h, andn,55h, or,56h, xor,57h, unpckl,14h, unpckh,15h
|
||||
macro instr#pd? dest*,src*
|
||||
require SSE2+
|
||||
SSE.basic_instruction 66h,ext,16,dest,src
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro cmppd? dest*,src*,code*
|
||||
require SSE2+
|
||||
SSE.basic_instruction_imm8 66h,0C2h,16,dest,src,code
|
||||
end macro
|
||||
|
||||
macro SSE.cmpsd? dest*,src*,code*
|
||||
require SSE2+
|
||||
SSE.basic_instruction_imm8 0F2h,0C2h,8,dest,src,code
|
||||
end macro
|
||||
|
||||
calminstruction cmpsd? args&
|
||||
match , args
|
||||
jno sse
|
||||
xcall x86.store_operand_prefix, (4)
|
||||
emit 1, 0A7h
|
||||
exit
|
||||
sse:
|
||||
arrange args, =SSE.=cmpsd args
|
||||
assemble args
|
||||
end calminstruction
|
||||
|
||||
iterate <cond,code>, eq,0, lt,1, le,2, unord,3, neq,4, nlt,5, nle,6, ord,7
|
||||
macro cmp#cond#pd? dest*,src*
|
||||
require SSE2+
|
||||
cmppd dest,src,code
|
||||
end macro
|
||||
macro cmp#cond#sd? dest*,src*
|
||||
require SSE2+
|
||||
cmpsd dest,src,code
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro shufpd? dest*,src*,imm*
|
||||
require SSE2+
|
||||
SSE.basic_instruction_imm8 66h,0C6h,16,dest,src,imm
|
||||
end macro
|
||||
|
||||
iterate <instr,ext>, movapd,28h, movupd,10h
|
||||
macro instr? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if (@dest.size or @src.size) and not 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
@src.opcode_prefix = 66h
|
||||
x86.store_instruction@src <0Fh,ext>,@dest.rm
|
||||
else if @dest.type = 'mem' & @src.type = 'mmreg'
|
||||
@dest.opcode_prefix = 66h
|
||||
x86.store_instruction@dest <0Fh,ext+1>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext>, movlpd,12h, movhpd,16h
|
||||
macro instr? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & @src.type = 'mem'
|
||||
if @dest.size <> 16 | @src.size and not 8
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 66h
|
||||
x86.store_instruction@src <0Fh,ext>,@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.opcode_prefix = 66h
|
||||
x86.store_instruction@dest <0Fh,ext+1>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro SSE.movsd? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
if @dest.size <> 16 | (@src.type = 'mem' & @src.size and not 8) | (@src.type = 'mmreg' & @src.size <> 16)
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 0F2h
|
||||
x86.store_instruction@src <0Fh,10h>,@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.opcode_prefix = 0F2h
|
||||
x86.store_instruction@dest <0Fh,11h>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
calminstruction movsd? args&
|
||||
match , args
|
||||
jno sse
|
||||
xcall x86.store_operand_prefix, (4)
|
||||
emit 1, 0A5h
|
||||
exit
|
||||
sse:
|
||||
arrange args, =SSE.=movsd args
|
||||
assemble args
|
||||
end calminstruction
|
||||
|
||||
iterate <instr,pre>, movdqa,66h, movdqu,0F3h
|
||||
macro instr? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if (@dest.size or @src.size) and not 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
@src.opcode_prefix = pre
|
||||
x86.store_instruction@src <0Fh,6Fh>,@dest.rm
|
||||
else if @dest.type = 'mem' & @src.type = 'mmreg'
|
||||
@dest.opcode_prefix = pre
|
||||
x86.store_instruction@dest <0Fh,7Fh>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext>, movntpd,2Bh, movntdq,0E7h
|
||||
macro instr? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mem' & @src.type = 'mmreg'
|
||||
if (@dest.size or @src.size) and not 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@dest.opcode_prefix = 66h
|
||||
x86.store_instruction@dest <0Fh,ext>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro movmskpd? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'reg' & @src.type = 'mmreg'
|
||||
if (@dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8)) | @src.size <> 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 66h
|
||||
x86.store_instruction@src <0Fh,50h>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro maskmovdqu? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & @src.type = 'mmreg'
|
||||
if (@dest.size or @src.size) <> 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 66h
|
||||
x86.store_instruction@src <0Fh,0F7h>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
iterate <instr,ext>, ucomisd,2Eh, comisd,2Fh
|
||||
macro instr? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
if @dest.size <> 16 | (@src.type = 'mem' & @src.size and not 8) | (@src.type = 'mmreg' & @src.size <> 16)
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 66h
|
||||
x86.store_instruction@src <0Fh,ext>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro cvtps2pd? dest*,src*
|
||||
require SSE2+
|
||||
SSE.basic_instruction 0,5Ah,8,dest,src
|
||||
end macro
|
||||
|
||||
macro cvtpd2ps? dest*,src*
|
||||
require SSE2+
|
||||
SSE.basic_instruction 66h,5Ah,16,dest,src
|
||||
end macro
|
||||
|
||||
macro cvtsd2ss? dest*,src*
|
||||
require SSE2+
|
||||
SSE.basic_instruction 0F2h,5Ah,8,dest,src
|
||||
end macro
|
||||
|
||||
macro cvtss2sd? dest*,src*
|
||||
require SSE2+
|
||||
SSE.basic_instruction 0F3h,5Ah,4,dest,src
|
||||
end macro
|
||||
|
||||
macro cvtdq2ps? dest*,src*
|
||||
require SSE2+
|
||||
SSE.basic_instruction 0,5Bh,16,dest,src
|
||||
end macro
|
||||
|
||||
macro cvtps2dq? dest*,src*
|
||||
require SSE2+
|
||||
SSE.basic_instruction 66h,5Bh,16,dest,src
|
||||
end macro
|
||||
|
||||
macro cvttps2dq? dest*,src*
|
||||
require SSE2+
|
||||
SSE.basic_instruction 0F3h,5Bh,16,dest,src
|
||||
end macro
|
||||
|
||||
macro cvttpd2dq? dest*,src*
|
||||
require SSE2+
|
||||
SSE.basic_instruction 66h,0E6h,16,dest,src
|
||||
end macro
|
||||
|
||||
macro cvtpd2dq? dest*,src*
|
||||
require SSE2+
|
||||
SSE.basic_instruction 0F2h,0E6h,16,dest,src
|
||||
end macro
|
||||
|
||||
macro cvtdq2pd? dest*,src*
|
||||
require SSE2+
|
||||
SSE.basic_instruction 0F3h,0E6h,8,dest,src
|
||||
end macro
|
||||
|
||||
macro movdq2q? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & @src.type = 'mmreg'
|
||||
if @dest.size <> 8 | @src.size <> 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 0F2h
|
||||
x86.store_instruction@src <0Fh,0D6h>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro movq2dq? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & @src.type = 'mmreg'
|
||||
if @dest.size <> 16 | @src.size <> 8
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 0F3h
|
||||
x86.store_instruction@src <0Fh,0D6h>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro cvtpi2pd? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
if @dest.size <> 16 | @src.size and not 8
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 66h
|
||||
x86.store_instruction@src <0Fh,2Ah>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro cvtsi2sd? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'reg')
|
||||
if @src.size = 0
|
||||
err 'operand size not specified'
|
||||
else if @dest.size <> 16 | @src.size < 4
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.select_operand_prefix@src @src.size
|
||||
@src.opcode_prefix = 0F2h
|
||||
x86.store_instruction@src <0Fh,2Ah>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
iterate <instr,ext>, cvttpd2pi,2Ch, cvtpd2pi,2Dh
|
||||
macro instr? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
if @dest.size <> 8 | @src.size and not 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 66h
|
||||
x86.store_instruction@src <0Fh,ext>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext>, cvttsd2si,2Ch, cvtsd2si,2Dh
|
||||
macro instr? dest*,src*
|
||||
require SSE2+
|
||||
x86.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
if @dest.size < 4 | (@src.type = 'mem' & @src.size and not 8) | (@src.type = 'mmreg' & @src.size <>16)
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.select_operand_prefix@src @dest.size
|
||||
@src.opcode_prefix = 0F2h
|
||||
x86.store_instruction@src <0Fh,ext>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext>, paddq,0D4h, pmuludq,0F4h, psubq,0FBh
|
||||
macro instr? dest*,src*
|
||||
require SSE2+
|
||||
MMX.basic_instruction ext,dest,src
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro movq? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
if (@src.type = 'mem' & @src.size and not 8) | (@src.type = 'mmreg' & @src.size <> @dest.size)
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if @dest.size = 8
|
||||
x86.store_instruction@src <0Fh,6Fh>,@dest.rm
|
||||
else
|
||||
@src.opcode_prefix = 0F3h
|
||||
x86.store_instruction@src <0Fh,7Eh>,@dest.rm
|
||||
end if
|
||||
else if @dest.type = 'mem' & @src.type = 'mmreg'
|
||||
if @dest.size and not 8
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if @src.size = 8
|
||||
x86.store_instruction@dest <0Fh,7Fh>,@src.rm
|
||||
else
|
||||
@dest.opcode_prefix = 66h
|
||||
x86.store_instruction@dest <0Fh,0D6h>,@src.rm
|
||||
end if
|
||||
else if @dest.type = 'reg' & @src.type = 'mmreg'
|
||||
if @dest.size <> 8
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if @src.size = 16
|
||||
@dest.opcode_prefix = 66h
|
||||
end if
|
||||
@dest.prefix = 48h
|
||||
x86.store_instruction@dest <0Fh,7Eh>,@src.rm
|
||||
else if @dest.type = 'mmreg' & @src.type = 'reg'
|
||||
if @src.size <> 8
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if @dest.size = 16
|
||||
@src.opcode_prefix = 66h
|
||||
end if
|
||||
@src.prefix = 48h
|
||||
x86.store_instruction@src <0Fh,6Eh>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro movd? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'reg')
|
||||
if @src.size and not 4
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
MMX.select_operand_prefix@src @dest.size
|
||||
x86.store_instruction@src <0Fh,6Eh>,@dest.rm
|
||||
else if (@dest.type = 'mem' | @dest.type = 'reg') & @src.type = 'mmreg'
|
||||
if @dest.size and not 4
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
MMX.select_operand_prefix@dest @src.size
|
||||
x86.store_instruction@dest <0Fh,7Eh>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro pinsrw? dest*,src*,sel*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if @dest.type = 'mmreg' & (@src.type = 'reg' | @src.type = 'mem') & @aux.type = 'imm'
|
||||
if (@src.type = 'reg' & @src.size <> 4) | (@src.type = 'mem' & @src.size and not 2) | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
MMX.select_operand_prefix@src @dest.size
|
||||
x86.store_instruction@src <0Fh,0C4h>,@dest.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro pextrw? dest*,src*,sel*
|
||||
require SSE2+
|
||||
x86.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if @dest.type = 'reg' & @src.type = 'mmreg' & @aux.type = 'imm'
|
||||
if x86.mode = 64 & @dest.size = 8
|
||||
@dest.size = 4
|
||||
end if
|
||||
if @dest.size <> 4 | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
MMX.select_operand_prefix@src @src.size
|
||||
x86.store_instruction@src <0Fh,0C5h>,@dest.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
iterate <instr,pre>, pshufd,66h, pshuflw,0F2h, pshufhw,0F3h
|
||||
macro instr? dest*,src*,sel*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm'
|
||||
if @dest.size <> 16 | @src.size and not 16 | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = pre
|
||||
x86.store_instruction@src <0Fh,70h>,@dest.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro pmovmskb? dest*,src*
|
||||
require SSE2+
|
||||
x86.parse_operand@dest dest
|
||||
SSE.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
|
||||
MMX.select_operand_prefix@src @src.size
|
||||
x86.store_instruction@src <0Fh,0D7h>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
iterate <instr,postbyte>, psrldq,3, pslldq,7
|
||||
macro instr? dest*,cnt*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
x86.parse_operand@aux cnt
|
||||
if @dest.type = 'mmreg' & @aux.type = 'imm'
|
||||
if @dest.size <> 16 | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@dest.opcode_prefix = 66h
|
||||
x86.store_instruction@dest <0Fh,73h>,postbyte,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext>, punpcklqdq,6Ch, punpckhqdq,6Dh
|
||||
macro instr? dest*,src*
|
||||
require SSE2+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
|
||||
if (@dest.size or @src.size) and not 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 66h
|
||||
x86.store_instruction@src <0Fh,ext>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro movnti? dest*,src*
|
||||
require SSE2+
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
if @dest.type = 'mem' & @src.type = 'reg'
|
||||
if @dest.size and not @src.size
|
||||
err 'operand sizes do not match'
|
||||
else if @src.size <> 4 & @src.size <> 8
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.select_operand_prefix@dest @src.size
|
||||
x86.store_instruction@dest <0Fh,0C3h>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro clflush? src*
|
||||
require SSE2+
|
||||
x86.parse_operand@src src
|
||||
if @src.type = 'mem'
|
||||
if @src.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,0AEh>,7
|
||||
else
|
||||
err 'invalid operand'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro lfence?
|
||||
require SSE2+
|
||||
db 0Fh,0AEh,0E8h
|
||||
end macro
|
||||
|
||||
macro mfence?
|
||||
require SSE2+
|
||||
db 0Fh,0AEh,0F0h
|
||||
end macro
|
84
toolchain/fasm2/include/iset/sse3.inc
Normal file
84
toolchain/fasm2/include/iset/sse3.inc
Normal file
@ -0,0 +1,84 @@
|
||||
|
||||
macro fisttp? src*
|
||||
require SSE3+
|
||||
x86.parse_operand@src src
|
||||
if @src.type = 'mem'
|
||||
if @src.size = 2
|
||||
x86.store_instruction@src 0DFh,1
|
||||
else if @src.size = 4
|
||||
x86.store_instruction@src 0DBh,1
|
||||
else if @src.size = 8
|
||||
x86.store_instruction@src 0DDh,1
|
||||
else if @src.size
|
||||
err 'invalid operand size'
|
||||
else
|
||||
err 'operand size not specified'
|
||||
end if
|
||||
else
|
||||
err 'invalid operand'
|
||||
end if
|
||||
end macro
|
||||
|
||||
iterate <instr,ext>, addsub,0D0h, hadd,7Ch, hsub,7Dh
|
||||
macro instr#pd? dest*,src*
|
||||
require SSE3+
|
||||
SSE.basic_instruction 66h,ext,16,dest,src
|
||||
end macro
|
||||
macro instr#ps? dest*,src*
|
||||
require SSE3+
|
||||
SSE.basic_instruction 0F2h,ext,16,dest,src
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,ext>, movsldup,12h, movshdup,16h
|
||||
macro instr? dest*,src*
|
||||
require SSE3+
|
||||
SSE.basic_instruction 0F3h,ext,16,dest,src
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro movddup? dest*,src*
|
||||
require SSE3+
|
||||
SSE.basic_instruction 0F2h,12h,8,dest,src
|
||||
end macro
|
||||
|
||||
macro lddqu? dest*,src*
|
||||
require SSE3+
|
||||
SSE.parse_operand@src dest
|
||||
SSE.parse_operand@src src
|
||||
if (@dest.size or @src.size) and not 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if @dest.type = 'mmreg' & @src.type = 'mem'
|
||||
@src.opcode_prefix = 0F2h
|
||||
x86.store_instruction@src <0Fh,0F0h>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
iterate <instr,supp>, pshufb,0, phaddw,1, phaddd,2, phaddsw,3, pmaddubsw,4, phsubw,5, phsubd,6, phsubsw,7, psignb,8, psignw,9, psignd,0Ah, pmulhrsw,0Bh, pabsb,1Ch, pabsw,1Dh, pabsd,1Eh
|
||||
macro instr? dest*,src*
|
||||
require SSSE3+
|
||||
MMX.basic_instruction <38h,supp>,dest,src
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro palignr? dest*,src*,aux*
|
||||
require SSSE3+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
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
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
if @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
MMX.select_operand_prefix@src @dest.size
|
||||
x86.store_instruction@src <0Fh,3Ah,0Fh>,@dest.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
278
toolchain/fasm2/include/iset/sse4.inc
Normal file
278
toolchain/fasm2/include/iset/sse4.inc
Normal file
@ -0,0 +1,278 @@
|
||||
|
||||
iterate <instr,supp>, ptest,17h, pmuldq,28h, pcmpeqq,29h, packusdw,2Bh, pminsb,38h, pminsd,39h, pminuw,3Ah, pminud,3Bh, pmaxsb,3Ch, pmaxsd,3Dh, pmaxuw,3Eh, pmaxud,3Fh, pmulld,40h, phminposuw,41h
|
||||
macro instr? dest*,src*
|
||||
require SSE4.1+
|
||||
SSE.basic_instruction 66h,<38h,supp>,16,dest,src
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,supp>, roundps,08h, roundpd,09h, roundss,0Ah, roundsd,0Bh, blendps,0Ch, blendpd,0Dh, pblendw,0Eh, dpps,40h, dppd,41h, mpsadbw,42h
|
||||
macro instr? dest*,src*,imm*
|
||||
require SSE4.1+
|
||||
SSE.basic_instruction_imm8 66h,<3Ah,supp>,16,dest,src,imm
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,supp>, pblendvb,10h, blendvps,14h, blendvpd,15h
|
||||
macro instr? dest*,src*,sel*
|
||||
require SSE4.1+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
SSE.parse_operand@aux sel
|
||||
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'mmreg' & @aux.size = 16 & @aux.rm = 0
|
||||
if @dest.size or @src.size and not 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 66h
|
||||
x86.store_instruction@src <0Fh,38h,supp>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <conv,code,msize>, bw,0,8, bd,1,4, bq,2,2, wd,3,8, wq,4,4, dq,5,8
|
||||
macro pmovsx#conv? dest*,src*
|
||||
require SSE4.1+
|
||||
SSE.basic_instruction 66h,<38h,20h+code>,msize,dest,src
|
||||
end macro
|
||||
macro pmovzx#conv? dest*,src*
|
||||
require SSE4.1+
|
||||
SSE.basic_instruction 66h,<38h,30h+code>,msize,dest,src
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro insertps? dest*,src*,sel*
|
||||
require SSE4.1+
|
||||
SSE.basic_instruction_imm8 66h,<3Ah,21h>,4,dest,src,sel
|
||||
end macro
|
||||
|
||||
macro extractps? dest*,src*,sel*
|
||||
require SSE4.1+
|
||||
x86.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if @dest.type = 'reg' & @src.type = 'mmreg' & @aux.type = 'imm'
|
||||
if x86.mode = 64 & @dest.size = 8
|
||||
@dest.size = 4
|
||||
end if
|
||||
if @dest.size <> 4 | @src.size and not 16 | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@dest.opcode_prefix = 66h
|
||||
x86.store_instruction@dest <0Fh,3Ah,17h>,@src.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro pinsrb? dest*,src*,sel*
|
||||
require SSE4.1+
|
||||
SSE.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if (@dest.type = 'mmreg' & @dest.size = 16) & (@src.type = 'reg' | @src.type = 'mem') & @aux.type = 'imm'
|
||||
if (@src.type = 'reg' & @src.size <> 4) | (@src.type = 'mem' & @src.size and not 1) | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 66h
|
||||
x86.store_instruction@src <0Fh,3Ah,20h>,@dest.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro pinsrd? dest*,src*,sel*
|
||||
require SSE4.1+
|
||||
SSE.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if (@dest.type = 'mmreg' & @dest.size = 16) & (@src.type = 'reg' | @src.type = 'mem') & @aux.type = 'imm'
|
||||
if @src.size and not 4 | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 66h
|
||||
x86.store_instruction@src <0Fh,3Ah,22h>,@dest.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro pinsrq? dest*,src*,sel*
|
||||
require SSE4.1+
|
||||
SSE.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if (@dest.type = 'mmreg' & @dest.size = 16) & (@src.type = 'reg' | @src.type = 'mem') & @aux.type = 'imm'
|
||||
if @src.size and not 8 | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if x86.mode < 64
|
||||
err 'instruction requires long mode'
|
||||
end if
|
||||
@src.opcode_prefix = 66h
|
||||
@src.rex_prefix = 48h
|
||||
x86.store_instruction@src <0Fh,3Ah,22h>,@dest.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro pextrb? dest*,src*,sel*
|
||||
require SSE4.1+
|
||||
x86.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if (@dest.type = 'reg' | @dest.type = 'mem') & (@src.type = 'mmreg' & @src.size = 16) & @aux.type = 'imm'
|
||||
if x86.mode = 64 & @dest.type = 'reg' & @dest.size = 8
|
||||
@dest.size = 4
|
||||
end if
|
||||
if (@dest.type = 'reg' & @dest.size <> 4) | (@dest.size = 'mem' & @dest.size and not 1) | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@dest.opcode_prefix = 66h
|
||||
x86.store_instruction@dest <0Fh,3Ah,14h>,@src.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro pextrw? dest*,src*,sel*
|
||||
require SSE4.1+
|
||||
x86.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if @dest.type = 'reg' & @src.type = 'mmreg' & @aux.type = 'imm'
|
||||
if x86.mode = 64 & @dest.size = 8
|
||||
@dest.size = 4
|
||||
end if
|
||||
if @dest.size <> 4 | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
MMX.select_operand_prefix@src @src.size
|
||||
x86.store_instruction@src <0Fh,0C5h>,@dest.rm,1,@aux.imm
|
||||
else if @dest.type = 'mem' & (@src.type = 'mmreg' & @src.size = 16) & @aux.type = 'imm'
|
||||
if @dest.size and not 2 | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@dest.opcode_prefix = 66h
|
||||
x86.store_instruction@dest <0Fh,3Ah,15h>,@src.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro pextrd? dest*,src*,sel*
|
||||
require SSE4.1+
|
||||
x86.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if (@dest.type = 'reg' | @dest.type = 'mem') & (@src.type = 'mmreg' & @src.size = 16) & @aux.type = 'imm'
|
||||
if x86.mode = 64 & @dest.type = 'reg' & @dest.size = 8
|
||||
@dest.size = 4
|
||||
end if
|
||||
if @dest.size and not 4 | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@dest.opcode_prefix = 66h
|
||||
x86.store_instruction@dest <0Fh,3Ah,16h>,@src.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro pextrq? dest*,src*,sel*
|
||||
require SSE4.1+
|
||||
x86.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
x86.parse_operand@aux sel
|
||||
if (@dest.type = 'reg' | @dest.type = 'mem') & (@src.type = 'mmreg' & @src.size = 16) & @aux.type = 'imm'
|
||||
if @dest.size and not 8 | @aux.size and not 1
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
if x86.mode < 64
|
||||
err 'instruction requires long mode'
|
||||
end if
|
||||
@dest.opcode_prefix = 66h
|
||||
@dest.rex_prefix = 48h
|
||||
x86.store_instruction@dest <0Fh,3Ah,16h>,@src.rm,1,@aux.imm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro movntdqa? dest*,src*
|
||||
require SSE4.1+
|
||||
SSE.parse_operand@dest dest
|
||||
SSE.parse_operand@src src
|
||||
if @dest.type = 'mmreg' & @src.type = 'mem'
|
||||
if (@dest.size or @src.size) and not 16
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 66h
|
||||
x86.store_instruction@src <0Fh,38h,2Ah>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
|
||||
iterate <instr,supp>, pcmpgtq,37h
|
||||
macro instr? dest*,src*
|
||||
require SSE4.2+
|
||||
SSE.basic_instruction 66h,<38h,supp>,16,dest,src
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
iterate <instr,supp>, pcmpestrm,60h, pcmpestri,61h, pcmpistrm,62h, pcmpistri,63h
|
||||
macro instr? dest*,src*,imm*
|
||||
require SSE4.2+
|
||||
SSE.basic_instruction_imm8 66h,<3Ah,supp>,16,dest,src,imm
|
||||
end macro
|
||||
macro v#instr? dest*,src*,imm*
|
||||
require AVX+
|
||||
AVX_512.single_source_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN,supp,16,dest,src,imm
|
||||
end macro
|
||||
end iterate
|
||||
|
||||
macro crc32? dest*,src*
|
||||
require SSE4.2+
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
if @dest.type = 'reg' & ( @src.type = 'reg' | @src.type = 'mem' )
|
||||
if @dest.size <> 4 & ( @dest.size <> 8 | x86.mode <> 64 )
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
@src.opcode_prefix = 0F2h
|
||||
if @src.size > 1
|
||||
x86.select_operand_prefix@src @src.size
|
||||
x86.store_instruction@src <0Fh,38h,0F1h>,@dest.rm
|
||||
else if @src.size > 0
|
||||
x86.store_instruction@src <0Fh,38h,0F0h>,@dest.rm
|
||||
else
|
||||
err 'operand size not specified'
|
||||
end if
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro popcnt? dest*,src*
|
||||
require POPCNT
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
if @dest.type = 'reg' & ( @src.type = 'reg' | @src.type = 'mem' )
|
||||
if @src.size and not @dest.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
@src.opcode_prefix = 0F3h
|
||||
if @dest.size > 1
|
||||
x86.select_operand_prefix@src @dest.size
|
||||
x86.store_instruction@src <0Fh,0B8h>,@dest.rm
|
||||
else
|
||||
err 'invalid operand size'
|
||||
end if
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
72
toolchain/fasm2/include/iset/vmx.inc
Normal file
72
toolchain/fasm2/include/iset/vmx.inc
Normal file
@ -0,0 +1,72 @@
|
||||
|
||||
iterate <instr,prefix,ext,postbyte>, vmxon,0F3h,0C7h,6, vmclear,66h,0C7h,6, \
|
||||
vmptrld,0,0C7h,6, vmptrst,0,0C7h,7
|
||||
|
||||
macro instr? src*
|
||||
require VMX
|
||||
x86.parse_operand@src src
|
||||
if @src.type = 'mem'
|
||||
if @src.size and not 8
|
||||
err 'invalid operand size'
|
||||
else
|
||||
@src.opcode_prefix = prefix
|
||||
x86.store_instruction@src <0Fh,ext>,postbyte
|
||||
end if
|
||||
else
|
||||
err 'invalid operand'
|
||||
end if
|
||||
end macro
|
||||
|
||||
end iterate
|
||||
|
||||
macro vmxoff?
|
||||
require VMX
|
||||
db 0Fh,1,0C4h
|
||||
end macro
|
||||
|
||||
macro vmcall?
|
||||
require VMX
|
||||
db 0Fh,1,0C1h
|
||||
end macro
|
||||
|
||||
macro vmlaunch?
|
||||
require VMX
|
||||
db 0Fh,1,0C2h
|
||||
end macro
|
||||
|
||||
macro vmresume?
|
||||
require VMX
|
||||
db 0Fh,1,0C3h
|
||||
end macro
|
||||
|
||||
macro vmread? dest*,src*
|
||||
require VMX
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
if @src.type = 'reg' & (@dest.type = 'mem' | @dest.type = 'reg')
|
||||
if (x86.mode < 64 & @src.size <> 4) | (x86.mode = 64 & @src.size <> 8)
|
||||
err 'invalid operand size'
|
||||
else if @dest.size and not @src.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
x86.store_instruction@dest <0Fh,78h>,@src.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro vmwrite? dest*,src*
|
||||
require VMX
|
||||
x86.parse_operand@dest dest
|
||||
x86.parse_operand@src src
|
||||
if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg')
|
||||
if (x86.mode < 64 & @dest.size <> 4) | (x86.mode = 64 & @dest.size <> 8)
|
||||
err 'invalid operand size'
|
||||
else if @src.size and not @dest.size
|
||||
err 'operand sizes do not match'
|
||||
end if
|
||||
x86.store_instruction@src <0Fh,79h>,@dest.rm
|
||||
else
|
||||
err 'invalid combination of operands'
|
||||
end if
|
||||
end macro
|
Reference in New Issue
Block a user