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

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