603 lines
16 KiB
PHP
603 lines
16 KiB
PHP
|
|
||
|
if ~ defined SSE2
|
||
|
|
||
|
restore SSE2 ; this ensures that symbol cannot be forward-referenced
|
||
|
SSE2 = 1
|
||
|
|
||
|
include 'sse.inc'
|
||
|
|
||
|
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*
|
||
|
SSE.basic_instruction 66h,ext,16,dest,src
|
||
|
end macro
|
||
|
macro instr#sd? dest*,src*
|
||
|
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*
|
||
|
SSE.basic_instruction 66h,ext,16,dest,src
|
||
|
end macro
|
||
|
end iterate
|
||
|
|
||
|
macro cmppd? dest*,src*,code*
|
||
|
SSE.basic_instruction_imm8 66h,0C2h,16,dest,src,code
|
||
|
end macro
|
||
|
|
||
|
macro SSE.cmpsd? dest*,src*,code*
|
||
|
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*
|
||
|
cmppd dest,src,code
|
||
|
end macro
|
||
|
macro cmp#cond#sd? dest*,src*
|
||
|
cmpsd dest,src,code
|
||
|
end macro
|
||
|
end iterate
|
||
|
|
||
|
macro shufpd? dest*,src*,imm*
|
||
|
SSE.basic_instruction_imm8 66h,0C6h,16,dest,src,imm
|
||
|
end macro
|
||
|
|
||
|
iterate <instr,ext>, movapd,28h, movupd,10h
|
||
|
macro instr? dest*,src*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
SSE.basic_instruction 0,5Ah,8,dest,src
|
||
|
end macro
|
||
|
|
||
|
macro cvtpd2ps? dest*,src*
|
||
|
SSE.basic_instruction 66h,5Ah,16,dest,src
|
||
|
end macro
|
||
|
|
||
|
macro cvtsd2ss? dest*,src*
|
||
|
SSE.basic_instruction 0F2h,5Ah,8,dest,src
|
||
|
end macro
|
||
|
|
||
|
macro cvtss2sd? dest*,src*
|
||
|
SSE.basic_instruction 0F3h,5Ah,4,dest,src
|
||
|
end macro
|
||
|
|
||
|
macro cvtdq2ps? dest*,src*
|
||
|
SSE.basic_instruction 0,5Bh,16,dest,src
|
||
|
end macro
|
||
|
|
||
|
macro cvtps2dq? dest*,src*
|
||
|
SSE.basic_instruction 66h,5Bh,16,dest,src
|
||
|
end macro
|
||
|
|
||
|
macro cvttps2dq? dest*,src*
|
||
|
SSE.basic_instruction 0F3h,5Bh,16,dest,src
|
||
|
end macro
|
||
|
|
||
|
macro cvttpd2dq? dest*,src*
|
||
|
SSE.basic_instruction 66h,0E6h,16,dest,src
|
||
|
end macro
|
||
|
|
||
|
macro cvtpd2dq? dest*,src*
|
||
|
SSE.basic_instruction 0F2h,0E6h,16,dest,src
|
||
|
end macro
|
||
|
|
||
|
macro cvtdq2pd? dest*,src*
|
||
|
SSE.basic_instruction 0F3h,0E6h,8,dest,src
|
||
|
end macro
|
||
|
|
||
|
macro movdq2q? dest*,src*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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
|
||
|
|
||
|
calminstruction MMX.select_operand_prefix rm_operand*,size*
|
||
|
local sym, prefix
|
||
|
check size = 16
|
||
|
jno no_prefix
|
||
|
compute prefix, 66h
|
||
|
arrange sym, rm_operand.=prefix
|
||
|
publish sym, prefix
|
||
|
exit
|
||
|
no_prefix:
|
||
|
check size <> 8
|
||
|
jno done
|
||
|
err 'invalid operand size'
|
||
|
done:
|
||
|
end calminstruction
|
||
|
|
||
|
calminstruction MMX.basic_instruction ext,dest,src
|
||
|
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 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,ext>, paddq,0D4h, pmuludq,0F4h, psubq,0FBh
|
||
|
macro instr? dest*,src*
|
||
|
MMX.basic_instruction ext,dest,src
|
||
|
end macro
|
||
|
end iterate
|
||
|
|
||
|
macro movq? dest*,src*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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*
|
||
|
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?
|
||
|
db 0Fh,0AEh,0E8h
|
||
|
end macro
|
||
|
|
||
|
macro mfence?
|
||
|
db 0Fh,0AEh,0F0h
|
||
|
end macro
|
||
|
|
||
|
end if
|