433 lines
12 KiB
PHP
433 lines
12 KiB
PHP
|
|
if ~ defined SSE
|
|
|
|
restore SSE ; this ensures that symbol cannot be forward-referenced
|
|
SSE = 1
|
|
|
|
include 'mmx.inc'
|
|
|
|
element SSE.reg
|
|
|
|
repeat 8, i:0
|
|
element xmm#i? : SSE.reg + i
|
|
end repeat
|
|
|
|
define x86.dqword? :16
|
|
define x86.xword? :16
|
|
|
|
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 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 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*
|
|
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*
|
|
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*
|
|
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*
|
|
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*
|
|
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*
|
|
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*
|
|
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*
|
|
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*
|
|
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*
|
|
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*
|
|
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*
|
|
MMX.basic_instruction ext,dest,src
|
|
end macro
|
|
end iterate
|
|
|
|
macro pinsrw? dest*,src*,sel*
|
|
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*
|
|
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*
|
|
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*
|
|
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*
|
|
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*
|
|
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*
|
|
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*
|
|
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*
|
|
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
|
|
|
|
end if |