add flat assembler toolchain

This commit is contained in:
2024-11-24 23:13:28 -05:00
parent 99e8e4072b
commit dbfd94ea40
302 changed files with 145599 additions and 0 deletions

View File

@ -0,0 +1,383 @@
include '8086.inc'
define @aux @aux
calminstruction push? src*
call x86.parse_operand@src, src
check @src.size and not 2
jno main
err 'invalid operand size'
main:
check @src.type = 'mem'
jyes push_mem
check @src.type = 'reg'
jyes push_reg
check @src.type = 'sreg'
jyes push_sreg
check @src.type = 'imm'
jyes push_imm
err 'invalid operand'
exit
push_mem:
xcall x86.store_instruction@src, (0FFh),(110b)
exit
push_reg:
emit 1, 50h + @src.rm
exit
push_sreg:
emit 1, 6 + @src.rm shl 3
exit
push_imm:
check @src.imm relativeto 0 & @src.imm < 80h & @src.imm >= -80h
jyes push_simm
check @src.imm relativeto 0 & @src.imm - 10000h >= -80h & @src.imm < 10000h
jyes push_simm_wrap
emit 1, 68h
asm dw @src.imm
exit
push_simm_wrap:
compute @src.imm, @src.imm - 10000h
push_simm:
emit 1, 6Ah
emit 1, @src.imm
exit
end calminstruction
calminstruction x86.pop_instruction size:0,dest*
call x86.parse_operand@dest, dest
check @dest.size and not 2
jno main
err 'invalid operand size'
main:
check @dest.type = 'mem'
jyes pop_mem
check @dest.type = 'reg'
jyes pop_reg
check @dest.type = 'sreg'
jyes pop_sreg
invalid_operand:
err 'invalid operand'
exit
pop_mem:
xcall x86.store_instruction@dest, (8Fh),(0)
exit
pop_reg:
emit 1, 58h + @dest.rm
exit
pop_sreg:
check @dest.rm = 1
jyes invalid_operand
emit 1, 7 + @dest.rm shl 3
exit
end calminstruction
iterate <instr>, push,pop
calminstruction instr? operand
local head, tail
match head tail, operand
jno plain
transform head, x86.compact
jno plain
match {head}, head
jno plain
loop:
arrange operand, =instr head
assemble operand
match head tail, tail
jno final
transform head, x86.compact
jno error
match {head}, head
jyes loop
error:
err 'only register operands allowed in compact syntax'
exit
final:
transform tail, x86.compact
jno error
match {operand}, tail
jno error
plain:
arrange operand, =instr operand
assemble operand
end calminstruction
end iterate
iterate <instr,opcode>, pusha,60h, popa,61h, insb,6Ch, outsb,6Eh, insw,6Dh, outsw,6Fh, leave,0C9h
calminstruction instr?
emit 1, opcode
end calminstruction
end iterate
calminstruction imul? dest*,src&
local size
call x86.parse_operand@dest, dest
match , src
jyes imul_rm
local src1, src2
match src1 =, src2, src
jyes imul_second_source
call x86.parse_operand@src, src
check @dest.size = 0 & @src.size = 0
jyes operand_size_not_specified
check @dest.size <> 0 & @src.size <> 0 & @dest.size <> @src.size
jyes operand_sizes_do_not_match
compute size, @dest.size or @src.size
check @src.type = 'imm' & @dest.type = 'reg'
jno invalid_combination_of_operands
compute @aux.type, @src.type
compute @aux.imm, @src.imm
compute @src.type, @dest.type
compute @src.mod, @dest.mod
compute @src.rm, @dest.rm
jump main
imul_second_source:
call x86.parse_operand@src, src1
call x86.parse_operand@aux, src2
check @dest.size = 0 & @src.size = 0 & @aux.size = 0
jyes operand_size_not_specified
compute size, @dest.size or @src.size or @aux.size
check (@dest.size & @dest.size <> size) | (@src.size & @src.size <> size) | (@aux.size & @aux.size <> size)
jyes operand_sizes_do_not_match
jump main
operand_size_not_specified:
err 'operand size not specified'
compute size, 0
jump main
operand_sizes_do_not_match:
err 'operand sizes do not match'
compute size, 0
jump main
main:
check @aux.type = 'imm' & ( @src.type = 'mem' | @src.type = 'reg' ) & @dest.type = 'reg' & size = 2
jyes imul_reg_rm_imm
invalid_combination_of_operands:
err 'invalid combination of operands'
exit
imul_rm:
check @dest.size
jyes imul_rm_size_ok
err 'operand size not specified'
imul_rm_size_ok:
check @dest.type = 'mem' | @dest.type = 'reg'
jno invalid_combination_of_operands
check @dest.size < 2
jyes imul_rm_8bit
xcall x86.store_instruction@dest, (0F7h),(5)
exit
imul_rm_8bit:
xcall x86.store_instruction@dest, (0F6h),(5)
exit
imul_reg_rm_imm:
check @aux.imm relativeto 0 & @aux.imm < 80h & @aux.imm >= -80h
jyes imul_reg_rm_simm
check @aux.imm relativeto 0 & @aux.imm - 10000h >= -80h & @aux.imm < 10000h
jyes imul_reg_rm_simm_wrap
xcall x86.store_instruction@src, (69h),@dest.rm,size,@aux.imm
exit
imul_reg_rm_simm_wrap:
compute @aux.imm, @aux.imm - 1 shl (size shl 3)
imul_reg_rm_simm:
xcall x86.store_instruction@src, (6Bh),@dest.rm,byte,@aux.imm
exit
end calminstruction
iterate <instr,postbyte>, rol,0, ror,1, rcl,2, rcr,3, shl,4, sal, 4, shr,5, sar,7
calminstruction instr? dest*,cnt*
call x86.parse_operand@dest, dest
call x86.parse_operand@src, cnt
check @dest.size = 0
jyes operand_size_not_specified
check @src.size and not 1
jyes invalid_operand_size
main:
check @src.type = 'reg' & @src.size = 1 & @src.rm = 1 & ( @dest.type = 'reg' | @dest.type = 'mem' )
jyes shift_rm_cl
check @src.type = 'imm' & ( @dest.type = 'reg' | @dest.type = 'mem' )
jyes shift_rm_imm
err 'invalid combination of operands'
exit
shift_rm_cl:
check @dest.size < 2
jyes shift_r8_cl
xcall x86.store_instruction@dest, (0D3h),(postbyte)
exit
shift_r8_cl:
xcall x86.store_instruction@dest, (0D2h),(postbyte)
exit
shift_rm_imm:
check @dest.size < 2
jyes shift_rm8_imm
check @src.imm = 1
jyes shift_rm_1
xcall x86.store_instruction@dest, (0C1h),(postbyte),byte,@src.imm
exit
shift_rm_1:
xcall x86.store_instruction@dest, (0D1h),(postbyte)
exit
shift_rm8_imm:
check @src.imm = 1
jyes shift_rm8_1
xcall x86.store_instruction@dest, (0C0h),(postbyte),byte,@src.imm
exit
shift_rm8_1:
xcall x86.store_instruction@dest, (0D0h),(postbyte)
exit
operand_size_not_specified:
err 'operand size not specified'
jump main
invalid_operand_size:
err 'invalid operand size'
jump main
end calminstruction
end iterate
calminstruction ins? dest*,src*
call x86.parse_operand@dest, dest
call x86.parse_operand@src, src
check @dest.size
jyes size_ok
err 'operand size not specified'
compute size, 0
size_ok:
check @src.type = 'reg' & @src.size = 2 & @src.rm = 2 & @dest.type = 'mem' & @dest.mod = 0 & @dest.rm = 5 & ( @dest.segment_prefix = 0 | @dest.segment_prefix = 26h )
jno invalid_combination_of_operands
check @dest.size = 2
jyes ins_word
assemble x86.insb
exit
ins_word:
assemble x86.insw
exit
invalid_combination_of_operands:
err 'invalid combination of operands'
exit
end calminstruction
calminstruction outs? dest*,src*
call x86.parse_operand@dest, dest
call x86.parse_operand@src, src
check @src.size
jyes size_ok
err 'operand size not specified'
size_ok:
check @dest.type = 'reg' & @dest.size = 2 & @dest.rm = 2 & @src.type = 'mem' & @src.mod = 0 & @src.rm = 4
jno invalid_combination_of_operands
check @src.segment_prefix = 0 | @src.segment_prefix = 3Eh
jyes segment_prefix_ok
emit 1, @src.segment_prefix
segment_prefix_ok:
check @src.size = 2
jyes outs_word
assemble x86.outsb
exit
outs_word:
assemble x86.outsw
exit
operand_size_not_specified:
err 'operand size not specified'
compute size, 0
jump size_ok
operand_sizes_do_not_match:
err 'operand sizes do not match'
compute size, 0
jump size_ok
invalid_combination_of_operands:
err 'invalid combination of operands'
exit
end calminstruction
calminstruction enter? alloc*,nesting*
call x86.parse_operand@src, alloc
call x86.parse_operand@aux, nesting
check (@src.size and not 2) | (@aux.size and not 1)
jno size_ok
err 'invalid operand size'
size_ok:
check @src.type = 'imm' & @aux.type = 'imm'
jno operand_ok
err 'invalid operand'
exit
operand_ok:
emit 1, 0C8h
asm dw @src.imm
emit 1, @aux.imm
end calminstruction
calminstruction bound? dest*,src*
call x86.parse_operand@dest, dest
call x86.parse_operand@src, src
check @src.type = 'mem' & @dest.type = 'reg'
jno invalid_combination_of_operands
check @dest.size = 2
jno invalid_operand_size
check @src.size and not @dest.size
jno size_ok
err 'operand sizes do not match'
size_ok:
xcall x86.store_instruction@src, (62h),@dest.rm
exit
invalid_operand_size:
err 'invalid operand size'
invalid_combination_of_operands:
err 'invalid combination of operands'
end calminstruction

View File

@ -0,0 +1,86 @@
include '80186.inc'
iterate <instr,opcode>, loadall,<0Fh,05h>, clts,<0Fh,06h>
calminstruction instr?
asm db opcode
end calminstruction
end iterate
calminstruction arpl? dest*,src*
call x86.parse_operand@dest, dest
call x86.parse_operand@src, src
check @src.type = 'reg' & (@dest.type = 'mem' | @dest.type = 'reg')
jno invalid_combination_of_operands
check @src.size = 2
jno invalid_operand_size
check @dest.size and not @src.size
jno size_ok
err 'operand sizes do not match'
jump size_ok
invalid_operand_size:
err 'invalid operand size'
size_ok:
xcall x86.store_instruction@dest, (63h),@src.rm
exit
invalid_combination_of_operands:
err 'invalid combination of operands'
end calminstruction
iterate <instr,ext,postbyte>, sldt,0,0, str,0,1, lldt,0,2, ltr,0,3, verr,0,4, verw,0,5, smsw,1,4, lmsw,1,6
calminstruction instr? dest*
call x86.parse_operand@dest, dest
check @dest.size and not 2
jno size_ok
err 'invalid operand size'
size_ok:
check @dest.type = 'reg' | @dest.type = 'mem'
jyes operand_ok
err 'invalid operand'
exit
operand_ok:
xcall x86.store_instruction@dest, <0Fh,ext>,(postbyte)
end calminstruction
end iterate
iterate <instr,postbyte>, lgdt,2, lidt,3, sgdt,0, sidt,1
calminstruction instr? dest*
call x86.parse_operand@dest, dest
check @dest.type = 'mem'
jyes operand_ok
err 'invalid operand'
exit
operand_ok:
check @dest.size and not 5
jno store_instruction
err 'invalid operand size'
store_instruction:
xcall x86.store_instruction@dest, <0Fh,1>,(postbyte)
exit
end calminstruction
end iterate
iterate <instr,ext>, lar,2, lsl,3
calminstruction instr? dest*,src*
call x86.parse_operand@dest, dest
call x86.parse_operand@src, src
check @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg')
jno invalid_combination_of_operands
check @src.size and not 2
jno size_ok
err 'invalid operand size'
size_ok:
xcall x86.store_instruction@src, <0Fh,ext>,@dest.rm
exit
invalid_combination_of_operands:
err 'invalid combination of operands'
end calminstruction
end iterate

View File

@ -0,0 +1,16 @@
if ~ defined i80287
restore i80287 ; this ensures that symbol cannot be forward-referenced
i80287 = 1
include '8087.inc'
purge feni?,fneni?,fdisi?,fndisi?
calminstruction fsetpm?
emit 1, 0DBh
emit 1, 0E4h
end calminstruction
end if

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,158 @@
if ~ defined i80387
restore i80387 ; this ensures that symbol cannot be forward-referenced
i80387 = 1
include '80287.inc'
purge fsetpm?
iterate <instr,opcode>, fprem1,<0D9h,0F5h>, fsincos,<0D9h,0FBh>, fsin,<0D9h,0FEh>, fcos,<0D9h,0FFh>, fucompp,<0DAh,0E9h>
calminstruction instr?
asm db opcode
end calminstruction
end iterate
iterate <instr,postbyte>, fucom,4, fucomp,5
calminstruction instr? src:st1
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.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.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.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.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.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.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
end if

View File

@ -0,0 +1,62 @@
include '80386.inc'
purge loadall?
purge xbts?,ibts?
iterate <instr,ext>, cmpxchg,0B0h, xadd,0C0h
calminstruction instr? dest*,src*
call x86.parse_operand@dest, dest
call x86.parse_operand@src, src
check @src.type = 'reg' & ( @dest.type = 'reg' | @dest.type = 'mem' )
jyes xadd_rm_reg
err 'invalid combination of operands'
exit
xadd_rm_reg:
check @dest.size and not @src.size
jno size_ok
err 'operand sizes do not match'
size_ok:
check @src.size > 1
jno xadd_rm_reg_8bit
call x86.select_operand_prefix@dest, @src.size
xcall x86.store_instruction@dest, <0Fh,ext+1>,@src.rm
exit
xadd_rm_reg_8bit:
xcall x86.store_instruction@dest, <0Fh,ext>,@src.rm
end calminstruction
end iterate
calminstruction bswap? dest*
call x86.parse_operand@dest, dest
check @dest.type = 'reg' & @dest.size = 4
jyes operand_ok
err 'invalid operand'
exit
operand_ok:
call x86.store_operand_prefix, @dest.size
emit 1, 0Fh
emit 1, 0C8h + @dest.rm and 111b
end calminstruction
calminstruction invlpg? dest*
call x86.parse_operand@dest, dest
check @dest.type = 'mem'
jyes operand_ok
err 'invalid operand'
exit
operand_ok:
xcall x86.store_instruction@dest, <0Fh,1>,(7)
end calminstruction
iterate <instr,opcode>, invd,<0Fh,8>, wbinvd,<0Fh,9>
define x86.instr? db opcode
calminstruction instr?
assemble x86.instr?
end calminstruction
end iterate

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,555 @@
if ~ defined i8087
restore i8087 ; this ensures that symbol cannot be forward-referenced
i8087 = 1
define x87 x87
element st?
repeat 8, i:0
element st#i? : st? + i
end repeat
define x86.qword? :8
define x86.tword? :10
define x86.tbyte? :10
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, 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?
asm db opcode
end calminstruction
end iterate
iterate op, eni, disi, clex, init
calminstruction f#op?
asm fwait?
asm fn#op?
end calminstruction
end iterate
iterate <instr,postbyte>, fadd,0, fmul,1, fsub,4, fsubr,5, fdiv,6, fdivr,7
calminstruction instr? operand&
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&
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 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 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 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 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 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 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 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 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 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 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 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 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.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.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.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
end if

View File

@ -0,0 +1,21 @@
iterate <instr,pfx>, adcx,66h, adox,0F3h
macro instr? dest*,src*
x86.parse_operand@dest dest
x86.parse_operand@src src
if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg')
if @src.size <> 0 & @src.size <> @dest.size
err 'operand sizes do not match'
end if
if @dest.size = 8 & x86.mode = 64
@src.prefix = 48h
else if @dest.size <> 4
err 'invalid operand size'
end if
@src.opcode_prefix = pfx
x86.store_instruction@src <0Fh,38h,0F6h>,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate

View File

@ -0,0 +1,43 @@
include 'sse.inc'
iterate <instr,supp>, aesdec,0DEh, aesenc,0DCh, aesimc,0DBh, aesdeclast,0DFh, aesenclast,0DDh
macro instr? dest*,src*
SSE.basic_instruction 66h,<38h,supp>,16,dest,src
end macro
end iterate
iterate <instr,supp>, aeskeygenassist,0DFh
macro instr? dest*,src*,imm*
SSE.basic_instruction_imm8 66h,<3Ah,supp>,16,dest,src,imm
end macro
end iterate
if defined AVX
iterate <instr,opcode>, aesenc,0DCh, aesenclast,0DDh, aesdec,0DEh, aesdeclast,0DFh
macro v#instr? dest*,src*,src2*
AVX.basic_instruction VEX_66_0F38_W0,opcode,16,dest,src,src2
end macro
end iterate
iterate <instr,opcode>, aesimc,0DBh
macro v#instr? dest*,src*
AVX.single_source_instruction VEX_66_0F38_W0,opcode,16,dest,src
end macro
end iterate
iterate <instr,opcode>, aeskeygenassist,0DFh
macro v#instr? dest*,src*,imm*
AVX.single_source_instruction_imm8 VEX_66_0F3A_W0,opcode,16,dest,src,imm
end macro
end iterate
end if

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,502 @@
if ~ defined AVX2
restore AVX2 ; this ensures that symbol cannot be forward-referenced
AVX2 = 1
include 'avx.inc'
iterate context, @dest,@src,@src2,@aux
namespace context
define visize
calminstruction AVX.parse_vsib_operand#context operand
local i, pre, suf
compute segment_prefix, 0
compute size, 0
compute displacement_size, 0
transform operand
match pre suf, operand
jno no_size_prefix
transform pre, x86
jno no_size_prefix
match :size, pre
jno no_size_prefix
arrange operand, suf
no_size_prefix:
match [address], operand
jyes memory_operand
match =ptr? address, operand
jyes memory_operand
jump invalid_operand
memory_operand:
compute type, 'mem'
match segment:address, address
jno segment_prefix_ok
check segment eq 1 elementof segment & 1 metadataof segment relativeto x86.sreg
jno invalid_operand
compute segment, 1 metadataof segment - x86.sreg
check segment >= 4
jyes segment_prefix_386
compute segment_prefix, 26h + segment shl 3
jump segment_prefix_ok
segment_prefix_386:
compute segment_prefix, 64h + segment-4
segment_prefix_ok:
match pre suf, address
jno no_address_size_prefix
transform pre, x86
jno no_address_size_prefix
match :pre, pre
jno no_address_size_prefix
arrange address, suf
check pre = 4 | pre = 8
jno invalid_address_size
compute mode, pre shl 3
no_address_size_prefix:
compute mode, 0
compute scale, 0
compute index, 0
compute base, 0
compute auto_relative, 0
check size
jyes size_override
compute size, sizeof address
size_override:
compute address, address
compute base_registers, 0
compute index_registers, 0
compute i, 1
extract_registers:
check i > elementsof address
jyes registers_extracted
check i metadataof address relativeto SSE.reg | i metadataof address relativeto AVX.reg
jyes index_term
check i metadataof address relativeto x86.r32 | i metadataof address relativeto x86.r64
jno next_term
compute base_registers, base_registers + i elementof address * i scaleof address
jump next_term
index_term:
compute index_registers, index_registers + i elementof address * i scaleof address
next_term:
compute i, i+1
jump extract_registers
registers_extracted:
compute displacement, address - base_registers - index_registers
compute auto_relative, 0
check elementsof index_registers = 1
jno invalid_address
compute scale, 1 scaleof index_registers
compute index, 0 scaleof (1 metadataof index_registers)
check scale and (scale-1) | scale > 8
jyes invalid_address
check 1 metadataof index_registers relativeto SSE.reg
jyes xmm_index
compute visize, 32
jump index_ok
xmm_index:
compute visize, 16
index_ok:
compute rm, 4
check elementsof base_registers = 1 & 1 scaleof base_registers = 1
jyes base_and_index
check elementsof base_registers = 0
jno invalid_address
compute base, 5
compute displacement_size, 4
compute mod, 0
compute mode, x86.mode
check mode > 16
jyes ready
compute mode, 32
jump ready
base_and_index:
compute base, 0 scaleof (1 metadataof base_registers)
check mode & mode <> 0 scaleof (1 metadataof (1 metadataof base_registers)) shl 3
jyes invalid_address
compute mode, 0 scaleof (1 metadataof (1 metadataof base_registers)) shl 3
setup_displacement:
check displacement relativeto 0
jno displacement_32bit
check displacement = 0 & rm and 111b <> 5 & (rm <> 4 | base and 111b <> 5)
jyes displacement_empty
check displacement < 80h & displacement >= -80h
jyes displacement_8bit
check displacement - 1 shl mode >= -80h & displacement < 1 shl mode
jyes displacement_8bit_wrap
displacement_32bit:
compute displacement_size, 4
compute mod, 2
jump ready
displacement_8bit_wrap:
compute displacement, displacement - 1 shl mode
displacement_8bit:
compute displacement_size, 1
compute mod, 1
jump ready
index_only:
compute displacement_size, 4
compute mod, 0
jump ready
displacement_empty:
compute displacement_size, 0
compute mod, 0
ready:
exit
invalid_operand:
err 'invalid operand'
exit
invalid_address:
err 'invalid address'
exit
invalid_address_size:
err 'invalid address size'
exit
end calminstruction
end namespace
end iterate
iterate <instr,opcode,asize>, vpgatherdd,90h,4, vpgatherqd,91h,8, vgatherdps,92h,4, vgatherqps,93h,8
macro instr? dest*,src*,mask*
AVX.parse_operand@dest dest
AVX.parse_vsib_operand@src src
AVX.parse_operand@aux mask
if @dest.type = 'mmreg' & @src.type = 'mem' & @aux.type = 'mmreg'
if @src.size and not 4 | (@dest.size > 16 & @dest.size * (asize shr 2) > @src.visize) | (@src.visize > 16 & @dest.size * (asize shr 2) < @src.visize)
err 'invalid operand size'
else if @aux.size <> @dest.size
err 'operand sizes do not match'
else if @dest.rm = @aux.rm | @dest.rm = @src.index | @aux.rm = @src.index
err 'disallowed combination of registers'
end if
AVX.store_instruction@src @src.visize,VEX_66_0F38_W0,opcode,@dest.rm,@aux.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,opcode,asize>, vpgatherdq,90h,4, vpgatherqq,91h,8, vgatherdpd,92h,4, vgatherqpd,93h,8
macro instr? dest*,src*,mask*
AVX.parse_operand@dest dest
AVX.parse_vsib_operand@src src
AVX.parse_operand@aux mask
if @dest.type = 'mmreg' & @src.type = 'mem' & @aux.type = 'mmreg'
if @src.size and not 8 | (@dest.size > 16 & @dest.size * (asize shr 2) > @src.visize * 2) | (@src.visize > 16 & @dest.size * (asize shr 2) < @src.visize * 2)
err 'invalid operand size'
else if @aux.size <> @dest.size
err 'operand sizes do not match'
else if @dest.rm = @aux.rm | @dest.rm = @src.index | @aux.rm = @src.index
err 'disallowed combination of registers'
end if
AVX.store_instruction@src @dest.size,VEX_66_0F38_W1,opcode,@dest.rm,@aux.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,opcode>, packsswb,63h, packuswb,67h, packssdw,6Bh, paddb,0FCh, paddw,0FDh, paddd,0FEh, paddq,0D4h, paddsb,0ECh, paddsw,0EDh, paddusb,0DCh, paddusw,0DDh, \
pand,0DBh, pandn,0DFh, pavgb,0E0h, pavgw,0E3h, pcmpeqb,74h, pcmpeqw,75h, pcmpeqd,76h, pcmpgtb,64h, pcmpgtw,65h, pcmpgtd,66h, \
pmaddwd,0F5h, pmaxsw,0EEh, pmaxub,0DEh, pminsw,0EAh, pminub,0DAh, pmulhuw,0E4h, pmulhw,0E5h, pmullw,0D5h, pmuludq,0F4h, \
por,0EBh, psadbw,0F6h, psubb,0F8h, psubw,0F9h, psubd,0FAh, psubq,0FBh, psubsb,0E8h, psubsw,0E9h, psubusb,0D8h, psubusw,0D9h, \
punpckhbw,68h, punpckhwd,69h, punpckhdq,6Ah, punpckhqdq,6Dh, punpcklbw,60h, punpcklwd,61h, punpckldq,62h, punpcklqdq,6Ch, pxor,0EFh
macro v#instr? dest*,src*,src2*
AVX.basic_instruction VEX_66_0F_W0,opcode,0,dest,src,src2
end macro
end iterate
iterate <instr,opcode>, packusdw,2Bh, pcmpeqq,29h, pcmpgtq,37h, phaddw,1, phaddd,2, phaddsw,3, phsubw,5, phsubd,6, phsubsw,7, pmaddubsw,4, \
pmaxsb,3Ch, pmaxsd,3Dh, pmaxuw,3Eh, pmaxud,3Fh, pminsb,38h, pminsd,39h, pminuw,3Ah, pminud,3Bh, pmulhrsw,0Bh, pmulld,40h, pmuldq,28h, \
pshufb,0, psignb,8, psignw,9, psignd,0Ah
macro v#instr? dest*,src*,src2*
AVX.basic_instruction VEX_66_0F38_W0,opcode,0,dest,src,src2
end macro
end iterate
iterate <instr,opcode>, mpsadbw,42h, palignr,0Fh, pblendd,02h
macro v#instr? dest*,src*,src2*,imm*
AVX.basic_instruction_imm8 VEX_66_0F3A_W0,opcode,0,dest,src,src2,imm
end macro
end iterate
iterate <instr,opcode>, pabsb,1Ch, pabsw,1Dh, pabsd,1Eh, pblendw,0Eh
macro v#instr? dest*,src*
AVX.single_source_instruction VEX_66_0F38_W0,opcode,0,dest,src
end macro
end iterate
iterate <instr,vex_mpw>, pshufd,VEX_66_0F_W0, pshufhw,VEX_F3_0F_W0, pshuflw,VEX_F2_0F_W0
macro v#instr? dest*,src*,imm*
AVX.single_source_instruction_imm8 vex_mpw,70h,0,dest,src,imm
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vpsllvd,VEX_66_0F38_W0,47h, vpsllvq,VEX_66_0F38_W1,47h, vpsrlvd,VEX_66_0F38_W0,45h, vpsrlvq,VEX_66_0F38_W1,45h, vpsravd,VEX_66_0F38_W0,46h
macro instr? dest*,src*,src2*
AVX.basic_instruction vex_mpw,opcode,0,dest,src,src2
end macro
end iterate
macro vpblendvb? dest*,src*,src2*,mask*
AVX.parse_operand@dest dest
AVX.parse_operand@src src
AVX.parse_operand@src2 src2
AVX.parse_operand@aux mask
if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'mmreg'
if @src.size <> @dest.size | @src2.size and not @dest.size | @aux.size <> @dest.size
err 'operand sizes do not match'
end if
AVX.store_instruction@src2 @dest.size,VEX_66_0F3A_W0,4Ch,@dest.rm,@src.rm,1,(@aux.rm and 1111b) shl 4
else
err 'invalid combination of operands'
end if
end macro
macro vpmovmskb? dest*,src*
x86.parse_operand@dest dest
AVX.parse_operand@src src
if @dest.type = 'reg' & @src.type = 'mmreg'
if (@dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8))
err 'invalid operand size'
end if
AVX.store_instruction@src @src.size,VEX_66_0F_W0,0D7h,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
iterate <instr,opcode,msize>, pmovsxbw,20h,8, pmovsxbd,21h,4, pmovsxbq,22h,2, pmovsxwd,23h,8, pmovsxwq,24h,4, pmovsxdq,25h,8, \
pmovzxbw,30h,8, pmovzxbd,31h,4, pmovzxbq,32h,2, pmovzxwd,33h,8, pmovzxwq,34h,4, pmovzxdq,35h,8
macro v#instr? dest*,src*
AVX.parse_operand@dest dest
AVX.parse_operand@src src
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
if (@src.type = 'mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not (msize * (@dest.size shr 4)))
err 'invalid operand size'
end if
AVX.store_instruction@src @dest.size,VEX_66_0F38_W0,opcode,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,postbyte>, pslldq,7, psrldq,3
macro v#instr dest*,src*,src2*
AVX.parse_operand@dest dest
AVX.parse_operand@src src
x86.parse_operand@src2 src2
if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'imm'
if @src2.size and not 1
err 'invalid operand size'
else if @src.size <> @dest.size
err 'operand sizes do not match'
end if
AVX.store_instruction@src @dest.size,VEX_66_0F_W0,73h,postbyte,@dest.rm,1,@src2.imm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,opcode_rrm,opcode,postbyte>, psllw,0F1h,71h,6, pslld,0F2h,72h,6, psllq,0F3h,73h,6, psraw,0E1h,71h,4, psrad,0E2h,72h,4, psrlw,0D1h,71h,2, psrld,0D2h,72h,2, psrlq,0D3h,73h,2
macro v#instr? dest*,src*,src2*
AVX.parse_operand@dest dest
AVX.parse_operand@src src
AVX.parse_operand@src2 src2
if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
if @src2.size and not 16
err 'invalid operand size'
else if @src.size <> @dest.size
err 'operand sizes do not match'
end if
AVX.store_instruction@src2 @dest.size,VEX_66_0F_W0,opcode_rrm,@dest.rm,@src.rm
else if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'imm'
if @src2.size and not 1
err 'invalid operand size'
else if @src.size <> @dest.size
err 'operand sizes do not match'
end if
AVX.store_instruction@src @dest.size,VEX_66_0F_W0,opcode,postbyte,@dest.rm,1,@src2.imm
else
err 'invalid combination of operands'
end if
end macro
end iterate
macro vmovntdqa? dest*,src*
AVX.parse_operand@dest dest
x86.parse_operand@src src
if @dest.type = 'mmreg' & @src.type = 'mem'
if @src.size and not @dest.size
err 'operand sizes do not match'
end if
AVX.store_instruction@src @dest.size,VEX_66_0F38_W0,2Ah,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
iterate <instr,w>, vpmaskmovd,0, vpmaskmovq,1
macro instr? dest*,src*,src2*
AVX.parse_operand@dest dest
AVX.parse_operand@src src
AVX.parse_operand@src2 src2
if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'mem'
if @src.size <> @dest.size | @src2.size and not @dest.size
err 'operand sizes do not match'
end if
AVX.store_instruction@src2 @dest.size,VEX_66_0F38_W#w,8Ch,@dest.rm,@src.rm
else if @dest.type = 'mem' & @src.type = 'mmreg' & @src2.type = 'mmreg'
if @src.size <> @src2.size | @dest.size and not @src.size
err 'operand sizes do not match'
end if
AVX.store_instruction@dest @src.size,VEX_66_0F38_W#w,8Eh,@src2.rm,@src.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
macro vbroadcasti128? dest*,src*
AVX.parse_operand@dest dest
AVX.parse_operand@src src
if @dest.type = 'mmreg' & @src.type = 'mem'
if @dest.size <> 32 | @src.size and not 16
err 'invalid operand size'
end if
AVX.store_instruction@src 32,VEX_66_0F38_W0,5Ah,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
macro vextracti128? dest*,src*,aux*
AVX.parse_operand@dest dest
AVX.parse_operand@src src
x86.parse_operand@aux aux
if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm'
if @dest.size and not 16 | @src.size <> 32 | @aux.size and not 1
err 'invalid operand size'
end if
AVX.store_instruction@dest 32,VEX_66_0F3A_W0,39h,@src.rm,,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
macro vinserti128? dest*,src*,src2*,aux*
AVX.parse_operand@dest dest
AVX.parse_operand@src src
AVX.parse_operand@src2 src2
x86.parse_operand@aux aux
if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mmreg' | @src2.type = 'mem') & @aux.type = 'imm'
if @dest.size <> 32 | @src.size <> 32 | @src2.size and not 16 | @aux.size and not 1
err 'invalid operand size'
end if
AVX.store_instruction@src2 32,VEX_66_0F3A_W0,38h,@dest.rm,@src.rm,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
macro vperm2i128? dest*,src*,src2*,imm*
AVX.basic_instruction_imm8 VEX_66_0F3A_W0,46h,32,dest,src,src2,imm
end macro
iterate <instr,opcode,msize>, vbroadcastss,18h,4, vpbroadcastb,78h,1, vpbroadcastw,79h,2, vpbroadcastd,58h,4, vpbroadcastq,59h,8
macro instr? dest*,src*
AVX.parse_operand@dest dest
AVX.parse_operand@src src
if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem')
if (@src.type='mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not msize)
err 'invalid operand size'
end if
AVX.store_instruction@src @dest.size,VEX_66_0F38_W0,opcode,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
macro vbroadcastsd? dest*,src*
AVX.parse_operand@dest dest
AVX.parse_operand@src src
if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem')
if @dest.size <> 32 | (@src.type='mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not 8)
err 'invalid operand size'
end if
AVX.store_instruction@src 32,VEX_66_0F38_W0,19h,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
iterate <instr,opcode>, vpermq,0, vpermpd,1
macro instr? dest*,src*,imm*
AVX.single_source_instruction_imm8 VEX_66_0F3A_W1,opcode,32,dest,src,imm
end macro
end iterate
iterate <instr,opcode>, vpermd,36h, vpermps,16h
macro instr? dest*,src*,src2*
AVX.basic_instruction VEX_66_0F38_W0,opcode,32,dest,src,src2
end macro
end iterate
end if

View File

@ -0,0 +1,10 @@
include 'avx512f.inc'
include 'avx512cd.inc'
include 'avx512vl.inc'
include 'avx512bw.inc'
include 'avx512dq.inc'
include 'avx512_ifma.inc'
include 'avx512_vbmi.inc'

View File

@ -0,0 +1,31 @@
if ~ defined AVX_512
include 'avx512f.inc'
end if
iterate <instr,opcode>, vp4dpwssd,52h, vp4dpwssds,53h
macro instr? dest*,src*,src2*
AVX_512.parse_k1z_operand@dest dest
match rsrc+=3, src
AVX_512.parse_operand@src rsrc
else
AVX_512.parse_operand@src src
end match
AVX_512.parse_operand@src2 src2
if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'mem'
if @dest.size <> 64 | @src2.size and not 16
err 'invalid operand size'
else if @dest.size <> @src.size
err 'operand sizes do not match'
end if
@src2.memsize = 0
AVX_512.store_instruction@src2 @dest.size,VEX_F2_0F38_W0,EVEX_REQUIRED,opcode,@dest.mask,@dest.rm,@src.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate

View File

@ -0,0 +1,29 @@
if ~ defined AVX_512
include 'avx512f.inc'
end if
iterate <instr,vex_mpw,opcode>, vpopcntb,VEX_66_0F38_W0,54h, vpopcntw,VEX_66_0F38_W1,54h
macro instr? dest*,src*
AVX_512.single_source_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src
end macro
end iterate
macro vpshufbitqmb? dest*,src*,src2*
AVX_512.parse_k1_operand@dest dest
AVX_512.parse_operand@src src
AVX_512.parse_operand@src2 src2
if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
if @src2.size and not @src.size
err 'operand sizes do not match'
end if
AVX_512.store_instruction@src2 @src.size,VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,8Fh,@dest.mask,@dest.rm,@src.rm
else
err 'invalid combination of operands'
end if
end macro

View File

@ -0,0 +1,15 @@
if ~ defined AVX_512
include 'avx512f.inc'
end if
iterate <instr,opcode>, vpmadd52luq,0B4h, vpmadd52huq,0B5h
macro instr? dest*,src*,src2*
AVX_512.basic_instruction_bcst VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2
end macro
end iterate

View File

@ -0,0 +1,22 @@
if ~ defined AVX_512
include 'avx512f.inc'
end if
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*
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*
AVX_512.basic_instruction_bcst VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2
end macro
end iterate

View File

@ -0,0 +1,65 @@
if ~ defined AVX_512
include 'avx512f.inc'
end if
iterate <instr,vex_mpw,opcode>, vpshldw,VEX_66_0F3A_W1,70h, vpshrdw,VEX_66_0F3A_W1,72h
macro instr? dest*,src*,src2*,aux*&
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*&
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*
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*
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*
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*
AVX_512.single_source_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src
end macro
end iterate

View File

@ -0,0 +1,14 @@
if ~ defined AVX_512
include 'avx512f.inc'
end if
iterate <instr,opcode>, vpdpbusd,50h, vpdpbusds,51h, vpdpwssd,52h, vpdpwssds,53h
macro instr? dest*,src*,src2*
AVX_512.basic_instruction_bcst VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,4,dest,src,src2
end macro
end iterate

View File

@ -0,0 +1,16 @@
if ~ defined AVX_512
include 'avx512f.inc'
end if
iterate <instr,unit,vex_mpw,opcode>, vpopcntd,4,VEX_66_0F38_W0,55h, vpopcntq,8,VEX_66_0F38_W1,55h
macro instr? dest*,src*
AVX_512.single_source_instruction_bcst vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src
end macro
end iterate

View File

@ -0,0 +1,494 @@
if ~ defined AVX_512
include 'avx512f.inc'
end if
iterate <t,vex_mpw,msize>, d,VEX_66_0F_W1,4, q,VEX_0F_W1,8
iterate <instr,opcode>, kand,41h, kandn,42h, knot,44h, kor,45h, kxnor,46h, kxor,47h, kadd,4Ah
macro instr#t? dest*,src*,src2*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
AVX_512.parse_operand@src2 src2
if @dest.type = 'maskreg' & @src.type = 'maskreg' & @src2.type = 'maskreg'
AVX.store_instruction@src2 32,vex_mpw,opcode,@dest.rm,@src.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,opcode>, knot,44h, kortest,98h, ktest,99h
macro instr#t? dest*,src*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'maskreg' & @src.type = 'maskreg'
AVX.store_instruction@src 16,vex_mpw,opcode,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
macro kmov#t? dest*,src*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'maskreg' & (@src.type = 'maskreg' | @src.type = 'mem')
if @src.type = 'mem' & @src.size and not msize
err 'invalid operand size'
end if
AVX.store_instruction@src 16,vex_mpw,90h,@dest.rm
else if @dest.type = 'mem' & @src.type = 'maskreg'
if @dest.size and not msize
err 'invalid operand size'
end if
AVX.store_instruction@dest 16,vex_mpw,91h,@src.rm
else if @dest.type = 'maskreg' & @src.type = 'reg'
if (msize < 8 & @src.size <> 4) | (msize = 8 & @src.size <> 8)
err 'invalid operand size'
else if msize = 8 & x86.mode < 64
err 'instruction requires long mode'
end if
AVX.store_instruction@src 16,vex_mpw,92h,@dest.rm
else if @dest.type = 'reg' & @src.type = 'maskreg'
if (msize < 8 & @dest.size <> 4) | (msize = 8 & @dest.size <> 8)
err 'invalid operand size'
else if msize = 8 & x86.mode < 64
err 'instruction requires long mode'
end if
AVX.store_instruction@src 16,vex_mpw,93h,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw,opcode>, kshiftrd,VEX_66_0F3A_W0,31h, kshiftrq,VEX_66_0F3A_W1,31h, \
kshiftld,VEX_66_0F3A_W0,33h, kshiftlq,VEX_66_0F3A_W1,33h
macro instr? dest*,src*,aux*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
x86.parse_operand@aux aux
if @dest.type = 'maskreg' & @src.type = 'maskreg' & @aux.type = 'imm'
if @aux.size and not 1
err 'invalid operand size'
end if
AVX.store_instruction@src 16,vex_mpw,opcode,@dest.rm,,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw>, kunpckwd,VEX_0F_W0, kunpckdq,VEX_0F_W1
macro 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 = 'maskreg' & @src.type = 'maskreg' & @src2.type = 'maskreg'
AVX.store_instruction@src2 32,vex_mpw,4Bh,@dest.rm,@src.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw,evex_f,opcode_rm,opcode_mr>, vmovdqu8,VEX_F2_0F_W0,EVEX_REQUIRED+EVEX_VL,6Fh,7Fh, vmovdqu16,VEX_F2_0F_W1,EVEX_REQUIRED+EVEX_VL,6Fh,7Fh
macro instr? dest*,src*
AVX_512.parse_k1z_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem')
if @src.size and not @dest.size
err 'operand sizes do not match'
end if
AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode_rm,@dest.mask,@dest.rm
else if @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_f,opcode_mr,@dest.mask,@src.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,opcode>, vpabsb,1Ch, vpabsw,1Dh
macro instr? dest*,src*
AVX_512.single_source_instruction VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,0,dest,src
end macro
end iterate
iterate <instr,opcode>, vpacksswb,63h, vpackuswb,67h, vpaddb,0FCh, vpaddw,0FDh, vpaddsb,0ECh, vpaddsw,0EDh, vpaddusb,0DCh, vpaddusw,0DDh, vpavgb,0E0h, vpavgw,0E3h, \
vpmaddwd,0F5h, vpmaxsw,0EEh, vpmaxub,0DEh, vpminsw,0EAh, vpminub,0DAh, vpmulhuw,0E4h, vpmulhw,0E5h, vpmullw,0D5h, \
vpsadbw,0F6h, vpsubb,0F8h, vpsubw,0F9h, vpsubsb,0E8h, vpsubsw,0E9h, vpsubusb,0D8h, vpsubusw,0D9h, \
vpunpckhbw,68h, vpunpckhwd,69h, vpunpcklbw,60h, vpunpcklwd,61h
macro instr? dest*,src*,src2*
AVX_512.basic_instruction VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode,0,dest,src,src2
end macro
end iterate
iterate <instr,opcode>, vpackssdw,6Bh
macro instr? dest*,src*,src2*
AVX_512.basic_instruction_bcst VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src,src2
end macro
end iterate
iterate <instr,opcode>, vpackusdw,2Bh
macro instr? dest*,src*,src2*
AVX_512.basic_instruction_bcst VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src,src2
end macro
end iterate
iterate <instr,opcode>, vpalignr,0Fh
macro instr? dest*,src*,src2*,imm*
AVX_512.basic_instruction_imm8 VEX_66_0F3A_W0,EVEX_AS_VEX+EVEX_VL,opcode,0,dest,src,src2,imm
end macro
end iterate
iterate <instr,opcode>, vpmaddubsw,4, vpmaxsb,3Ch, vpmaxuw,3Eh, vpminsb,38h, vpminuw,3Ah, vpmulhrsw,0Bh, vpshufb,0
macro instr? dest*,src*,src2*
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>, vpcmpeqb,74h, vpcmpeqw,75h, vpcmpgtb,64h, vpcmpgtw,65h
macro instr? dest*,src*,src2*
AVX_512.parse_k1_operand@dest dest
AVX_512.parse_operand@src src
AVX_512.parse_operand@src2 src2
if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
if @src2.size and not @src.size
err 'operand sizes do not match'
end if
AVX_512.store_instruction@src2 @src.size,VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm
else if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
if @src.size <> @dest.size | @src2.size and not @dest.size
err 'operand sizes do not match'
end if
AVX_512.store_instruction@src2 @src.size,VEX_66_0F_W0,EVEX_FORBIDDEN,opcode,@dest.mask,@dest.rm,@src.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
macro vpextrb? dest*,src*,aux*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
x86.parse_operand@aux aux
if (@dest.type = 'reg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm'
if (@dest.type = 'reg' & @dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8)) | (@dest.type = 'mem' & @dest.size and not 1) | @src.size <> 16 | @aux.size and not 1
err 'invalid operand size'
end if
@dest.memsize = 1
AVX_512.store_instruction@dest 16,VEX_66_0F3A_W0,EVEX_AS_VEX,14h,0,@src.rm,,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
macro vpextrw? dest*,src*,aux*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
x86.parse_operand@aux aux
if @dest.type = 'reg' & @src.type = 'mmreg' & @aux.type = 'imm'
if @dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8) | @src.size <> 16 | @aux.size and not 1
err 'invalid operand size'
end if
AVX_512.store_instruction@src 16,VEX_66_0F_W0,EVEX_AS_VEX,0C5h,0,@dest.rm,,1,@aux.imm
else if @dest.type = 'mem' & @src.type = 'mmreg' & @aux.type = 'imm'
if @dest.size and not 2 | @src.size <> 16 | @aux.size and not 1
err 'invalid operand size'
end if
@dest.memsize = 2
AVX_512.store_instruction@dest 16,VEX_66_0F3A_W0,EVEX_AS_VEX,15h,0,@src.rm,,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
iterate <instr,vex_mpw,opcode,msize>, vpinsrb,VEX_66_0F3A_W0,20h,1, vpinsrw,VEX_66_0F_W0,0C4h,2
macro instr? dest*,src*,src2*,aux*
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 = 'reg' | @src2.type = 'mem') & @aux.type = 'imm'
if @dest.size <> 16 | @src.size <> 16 | (@src2.type = 'reg' & @src2.size <> 4) | (@src2.type = 'mem' & @src2.size and not msize) | @aux.size and not 1
err 'invalid operand size'
end if
@src2.memsize = msize
AVX_512.store_instruction@src2 16,vex_mpw,EVEX_AS_VEX,opcode,0,@dest.rm,@src.rm,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,opcode,msize>, vpmovsxbw,20h,8, vpmovzxbw,30h,8
macro instr? dest*,src*
AVX_512.parse_k1z_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
@src.memsize = msize * (@dest.size shr 4)
if (@src.type = 'mmreg' & @src.size <> (@src.memsize-1) and not 15 + 16) | (@src.type = 'mem' & @src.size and not @src.memsize)
err 'invalid operand size'
end if
AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,@dest.mask,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw>, vpshufhw,VEX_F3_0F_W0, vpshuflw,VEX_F2_0F_W0
macro instr? dest*,src*,aux*
AVX_512.parse_k1z_operand@dest dest
AVX_512.parse_operand@src src
x86.parse_operand@aux aux
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm'
if @aux.size and not 1
err 'invalid operand size'
else if @src.size and not @dest.size
err 'operand sizes do not match'
end if
AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_AS_VEX+EVEX_VL,70h,@dest.mask,@dest.rm,,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,postbyte>, vpslldq,7, vpsrldq,3
macro instr? dest*,src*,aux*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
x86.parse_operand@aux aux
if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') & @aux.type = 'imm'
if @aux.size and not 1
err 'invalid operand size'
else if @src.size <> @dest.size
err 'operand sizes do not match'
end if
if @src.type = 'mem'
AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL,73h,0,postbyte,@dest.rm,1,@aux.imm
else
AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL,73h,0,postbyte,@dest.rm,1,@aux.imm
end if
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,opcode_rrm,opcode,postbyte>, vpsllw,0F1h,71h,6, vpsraw,0E1h,71h,4, vpsrlw,0D1h,71h,2
macro instr? dest*,src*,src2*
AVX_512.parse_k1z_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')
@src2.memsize = 16
if @src2.size and not @src2.memsize
err 'invalid operand size'
else if @src.size <> @dest.size
err 'operand sizes do not match'
end if
AVX_512.store_instruction@src2 @dest.size,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode_rrm,@dest.mask,@dest.rm,@src.rm
else if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') & @src2.type = 'imm'
if @src2.size and not 1
err 'invalid operand size'
else if @src.size <> @dest.size
err 'operand sizes do not match'
end if
if @src.type = 'mem'
AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,postbyte,@dest.rm,1,@src2.imm
else
AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode,@dest.mask,postbyte,@dest.rm,1,@src2.imm
end if
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vdbpsadbw,VEX_66_0F3A_W0,42h
macro instr? dest*,src*,src2*,aux*&
AVX_512.basic_instruction_imm8 vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src,src2,aux
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vpblendmb,VEX_66_0F38_W0,66h, vpblendmw,VEX_66_0F38_W1,66h
macro instr? dest*,src*,src2*&
AVX_512.basic_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src,src2
end macro
end iterate
iterate <instr,opcode,opcode_g,msize>, vpbroadcastb,78h,7Ah,1, vpbroadcastw,79h,7Bh,2
macro instr? dest*,src*
AVX_512.parse_k1z_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem')
if (@src.type='mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not msize)
err 'invalid operand size'
end if
@src.memsize = msize
AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,@dest.mask,@dest.rm
else if @dest.type = 'mmreg' & @src.type = 'reg'
if @src.size <> msize & (@src.size <> 4 | msize = 8)
err 'invalid operand size'
end if
@src.memsize = msize
if msize = 8
AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode_g,@dest.mask,@dest.rm
else
AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode_g,@dest.mask,@dest.rm
end if
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vpcmpb,VEX_66_0F3A_W0,3Fh, vpcmpub,VEX_66_0F3A_W0,3Eh, vpcmpw,VEX_66_0F3A_W1,3Fh, vpcmpuw,VEX_66_0F3A_W1,3Eh
macro instr? dest*,src*,src2*,aux*
AVX_512.parse_k1_operand@dest dest
AVX_512.parse_operand@src src
AVX_512.parse_operand@src2 src2
x86.parse_operand@aux aux
if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm'
if @src2.size and not @src.size | @aux.size and not 1
err 'operand sizes do not match'
end if
AVX_512.store_instruction@src2 @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vpermw,VEX_66_0F38_W1,8Dh, vpermi2w,VEX_66_0F38_W1,75h, vpermt2w,VEX_66_0F38_W1,7Dh
macro instr? dest*,src*,src2*
AVX_512.basic_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src,src2
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vpmovb2m,VEX_F3_0F38_W0,29h, vpmovw2m,VEX_F3_0F38_W1,29h
macro instr? dest*,src*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'maskreg' & @src.type = 'mmreg'
AVX_512.store_instruction@src @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vpmovm2b,VEX_F3_0F38_W0,28h, vpmovm2w,VEX_F3_0F38_W1,28h
macro instr? dest*,src*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'mmreg' & @src.type = 'maskreg'
AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,ratio,opcode>, vpmovuswb,2,10h, vpmovswb,2,20h, vpmovwb,2,30h
macro instr? dest*,src*
AVX_512.parse_k1z_operand@dest dest
AVX_512.parse_operand@src src
if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg'
@dest.memsize = @src.size / ratio
if (@dest.type = 'mmreg' & @dest.size <> (@dest.memsize-1) and not 15 + 16) | (@dest.type = 'mem' & @dest.size and not @dest.memsize)
err 'invalid operand size'
end if
AVX_512.store_instruction@dest @src.size,VEX_F3_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@src.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,opcode>, vpsllvw,12h, vpsrlvw,10h, vpsravw,11h
macro instr? dest*,src*,src2*
AVX_512.basic_instruction VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src,src2
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vptestnmb,VEX_F3_0F38_W0,26h, vptestnmw,VEX_F3_0F38_W1,26h, vptestmb,VEX_66_0F38_W0,26h, vptestmw,VEX_66_0F38_W1,26h
macro instr? dest*,src*,src2*
AVX_512.parse_k1_operand@dest dest
AVX_512.parse_operand@src src
AVX_512.parse_operand@src2 src2
if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg')
if @src2.size and not @src.size
err 'operand sizes do not match'
end if
AVX_512.store_instruction@src2 @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate

View File

@ -0,0 +1,29 @@
if ~ defined AVX_512
include 'avx512f.inc'
end if
iterate <instr,vex_mpw,opcode>, vpbroadcastmb2q,VEX_F3_0F38_W1,2Ah, vpbroadcastmw2d,VEX_F3_0F38_W0,3Ah
macro instr? dest*,src*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'mmreg' & @src.type = 'maskreg'
AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,unit,vex_mpw,opcode>, vpconflictd,4,VEX_66_0F38_W0,0C4h, vpconflictq,8,VEX_66_0F38_W1,0C4h, vplzcntd,4,VEX_66_0F38_W0,44h, vplzcntq,8,VEX_66_0F38_W1,44h
macro instr? dest*,src*&
AVX_512.single_source_instruction_bcst vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src
end macro
end iterate

View File

@ -0,0 +1,463 @@
if ~ defined AVX_512
include 'avx512f.inc'
end if
iterate <instr,opcode>, kandb,41h, kandnb,42h, knotb,44h, korb,45h, kxnorb,46h, kxorb,47h, kaddb,4Ah
macro 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 = 'maskreg' & @src.type = 'maskreg' & @src2.type = 'maskreg'
AVX.store_instruction@src2 32,VEX_66_0F_W0,opcode,@dest.rm,@src.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,opcode>, knotb,44h, kortestb,98h, ktestb,99h
macro instr? dest*,src*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'maskreg' & @src.type = 'maskreg'
AVX.store_instruction@src 16,VEX_66_0F_W0,opcode,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
macro kmovb? dest*,src*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'maskreg' & (@src.type = 'maskreg' | @src.type = 'mem')
if @src.type = 'mem' & @src.size and not 1
err 'invalid operand size'
end if
AVX.store_instruction@src 16,VEX_66_0F_W0,90h,@dest.rm
else if @dest.type = 'mem' & @src.type = 'maskreg'
if @dest.size and not 1
err 'invalid operand size'
end if
AVX.store_instruction@dest 16,VEX_66_0F_W0,91h,@src.rm
else if @dest.type = 'maskreg' & @src.type = 'reg'
if @src.size <> 4
err 'invalid operand size'
end if
AVX.store_instruction@src 16,VEX_66_0F_W0,92h,@dest.rm
else if @dest.type = 'reg' & @src.type = 'maskreg'
if @dest.size <> 4
err 'invalid operand size'
end if
AVX.store_instruction@src 16,VEX_66_0F_W0,93h,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
macro kaddw? dest*,src*,src2*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
AVX_512.parse_operand@src2 src2
if @dest.type = 'maskreg' & @src.type = 'maskreg' & @src2.type = 'maskreg'
AVX.store_instruction@src2 32,VEX_0F_W0,opcode,@dest.rm,@src.rm
else
err 'invalid combination of operands'
end if
end macro
macro ktestw? dest*,src*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'maskreg' & @src.type = 'maskreg'
AVX.store_instruction@src 16,VEX_0F_W0,opcode,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
iterate <instr,vex_mpw,opcode>, kshiftrb,VEX_66_0F3A_W0,30h, kshiftlb,VEX_66_0F3A_W0,32h
macro instr? dest*,src*,aux*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
x86.parse_operand@aux aux
if @dest.type = 'maskreg' & @src.type = 'maskreg' & @aux.type = 'imm'
if @aux.size and not 1
err 'invalid operand size'
end if
AVX.store_instruction@src 16,vex_mpw,opcode,@dest.rm,,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,opcode>, and,54h, andn,55h, or,56h, xor,57h
macro v#instr#pd? dest*,src*,src2*&
AVX_512.basic_instruction_bcst VEX_66_0F_W0,EVEX_W1+EVEX_VL,opcode,8,dest,src,src2
end macro
macro v#instr#ps? dest*,src*,src2*&
AVX_512.basic_instruction_bcst VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src,src2
end macro
end iterate
iterate <instr,opcode>, vbroadcastf32x2,19h, vbroadcasti32x2,59h
macro instr? dest*,src*
AVX_512.parse_k1z_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem')
if @dest.size = 16 | (@src.type = 'mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not 8)
err 'invalid operand size'
end if
@src.memsize = 8
AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw,opcode,msize>, vbroadcastf32x8,VEX_66_0F38_W0,1Bh,32, vbroadcastf64x2,VEX_66_0F38_W1,1Ah,16, \
vbroadcasti32x8,VEX_66_0F38_W0,5Bh,32, vbroadcasti64x2,VEX_66_0F38_W1,5Ah,16
macro instr? dest*,src*
AVX_512.parse_k1z_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'mmreg' & @src.type = 'mem'
if @dest.size <= msize | @src.size and not msize
err 'invalid operand size'
end if
@src.memsize = msize
AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vcvtpd2qq,VEX_66_0F_W1,7Bh, vcvtpd2uqq,VEX_66_0F_W1,79h, \
vcvtqq2pd,VEX_F3_0F_W1,0E6h, vcvtuqq2pd,VEX_F3_0F_W1,7Ah
macro instr? dest*,src*&
AVX_512.single_source_instruction_bcst_er vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vcvttpd2qq,VEX_66_0F_W1,7Ah, vcvttpd2uqq,VEX_66_0F_W1,78h
macro instr? dest*,src*&
AVX_512.single_source_instruction_bcst_sae vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vcvtps2qq,VEX_66_0F_W0,7Bh, vcvtps2uqq,VEX_66_0F_W0,79h
macro instr? dest*,src_er*&
AVX_512.parse_k1z_operand@dest dest
match src=,er, src_er
AVX_512.parse_operand@src src
AVX_512.parse_er@src er,32
else
AVX_512.parse_bcst_operand@src src_er,4
end match
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
if (@src.type = 'mem' & @src.size and not (@dest.size shr 1)) | (@src.type = 'mmreg' & (@dest.size shr 1 - 1) and not 15 + 16 <> @src.size)
err 'invalid operand size'
end if
if @src.memsize = 0
@src.memsize = @dest.size shr 1
end if
AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vcvtqq2ps,VEX_0F_W1,5Bh, vcvtuqq2ps,VEX_F2_0F_W1,7Ah
macro instr? dest*,src_er*&
AVX_512.parse_k1z_operand@dest dest
match src=,er, src_er
AVX_512.parse_operand@src src
AVX_512.parse_er@src er
else
AVX_512.parse_bcst_operand@src src_er,8
end match
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
if @src.size = 0
if @dest.size = 16
err 'operand size not specified'
else
@src.size = 64
end if
end if
if (@src.size shr 1 - 1) and not 15 + 16 <> @dest.size | @src.size > 64
err 'invalid operand size'
end if
AVX_512.store_instruction@src @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vcvttps2qq,VEX_66_0F_W0,7Ah, vcvttps2uqq,VEX_66_0F_W0,78h
macro instr? dest*,src_sae*&
AVX_512.parse_k1z_operand@dest dest
match src=,sae, src_sae
AVX_512.parse_operand@src src
AVX_512.parse_sae @src,sae
else
AVX_512.parse_bcst_operand@src src_sae,4
end match
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
if (@src.type = 'mem' & @src.size and not (@dest.size shr 1)) | (@src.type = 'mmreg' & (@dest.size shr 1 - 1) and not 15 + 16 <> @src.size)
err 'invalid operand size'
end if
if @src.memsize = 0
@src.memsize = @dest.size shr 1
end if
AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw,opcode,msize>, vextractf32x8,VEX_66_0F3A_W0,1Bh,32, vextractf64x2,VEX_66_0F3A_W1,19h,16, \
vextracti32x8,VEX_66_0F3A_W0,3Bh,32, vextracti64x2,VEX_66_0F3A_W1,39h,16
macro instr? dest*,src*,aux*
AVX_512.parse_k1z_operand@dest dest
AVX_512.parse_operand@src src
x86.parse_operand@aux aux
if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm'
if @dest.size and not msize | @src.size <= msize | @aux.size and not 1
err 'invalid operand size'
end if
@dest.memsize = msize
AVX_512.store_instruction@dest @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@src.rm,,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw,opcode,msize>, vinsertf32x8,VEX_66_0F3A_W0,1Ah,32, vinsertf64x2,VEX_66_0F3A_W1,18h,16, \
vinserti32x8,VEX_66_0F3A_W0,3Ah,32, vinserti64x2,VEX_66_0F3A_W1,38h,16
macro instr? dest*,src*,src2*,aux*
AVX_512.parse_k1z_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 = 'mmreg' | @src2.type = 'mem') & @aux.type = 'imm'
if @dest.size <= msize | @src.size <= msize | @src2.size and not msize | @aux.size and not 1
err 'invalid operand size'
end if
@src2.memsize = msize
AVX_512.store_instruction@src2 @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,unit,vex_mpw>, vfpclasspd,8,VEX_66_0F3A_W1, vfpclassps,4,VEX_66_0F3A_W0
macro instr? dest*,src*,aux*
AVX_512.parse_k1_operand@dest dest
AVX_512.parse_bcst_operand@src src,unit
x86.parse_operand@aux aux
if @dest.type = 'maskreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm'
if @src.size = 0
err 'operand size not specified'
else if (@src.size <> 16 & @src.size <> 32 & @src.size <> 64) | @aux.size and not 1
err 'invalid operand size'
end if
AVX_512.store_instruction@src @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,66h,@dest.mask,@dest.rm,,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,unit,vex_mpw>, vfpclasssd,8,VEX_66_0F3A_W1, vfpclassss,4,VEX_66_0F3A_W0
macro instr? dest*,src*,aux*
AVX_512.parse_k1_operand@dest dest
AVX_512.parse_operand@src src
x86.parse_operand@aux aux
if @dest.type = 'maskreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm'
if (@src.type = 'mem' & @src.size and not unit) | (@src.type = 'mmreg' & @src.size <> 16) | @aux.size and not 1
err 'invalid operand size'
end if
@src.memsize = 16
AVX_512.store_instruction@src @src.size,vex_mpw,EVEX_REQUIRED,67h,@dest.mask,@dest.rm,,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
end iterate
macro vpextrd? dest*,src*,aux*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
x86.parse_operand@aux aux
if (@dest.type = 'reg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm'
if (@dest.type = 'reg' & @dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8)) | (@dest.type = 'mem' & @dest.size and not 4) | @src.size <> 16 | @aux.size and not 1
err 'invalid operand size'
end if
@dest.memsize = 4
AVX_512.store_instruction@dest 16,VEX_66_0F3A_W0,EVEX_AS_VEX,16h,0,@src.rm,,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
macro vpinsrd? dest*,src*,src2*,aux*
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 = 'reg' | @src2.type = 'mem') & @aux.type = 'imm'
if @dest.size <> 16 | @src.size <> 16 | (@src2.type = 'reg' & @src2.size <> 4) | (@src2.type = 'mem' & @src2.size and not 4) | @aux.size and not 1
err 'invalid operand size'
end if
@src2.memsize = 4
AVX_512.store_instruction@src2 16,VEX_66_0F3A_W0,EVEX_AS_VEX,22h,0,@dest.rm,@src.rm,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
macro vpextrq? dest*,src*,aux*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
x86.parse_operand@aux aux
if (@dest.type = 'reg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm'
if @dest.size and not 8 | @src.size <> 16 | @aux.size and not 1
err 'invalid operand size'
end if
if x86.mode < 64
err 'instruction requires long mode'
end if
@dest.memsize = 8
AVX_512.store_instruction@dest 16,VEX_66_0F3A_W1,EVEX_AS_VEX,16h,0,@src.rm,,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
macro vpinsrq? dest*,src*,src2*,aux*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
x86.parse_operand@src2 src2
x86.parse_operand@aux aux
if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'reg' | @src2.type = 'mem') & @aux.type = 'imm'
if @dest.size <> 16 | @src.size <> 16 | @src2.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
@src2.memsize = 8
AVX_512.store_instruction@src2 16,VEX_66_0F3A_W1,EVEX_AS_VEX,22h,0,@dest.rm,@src.rm,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro
macro vpmullq? dest*,src*,src2*
AVX_512.basic_instruction_bcst VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,40h,8,dest,src,src2
end macro
iterate <instr,vex_mpw,opcode>, vpmovm2d,VEX_F3_0F38_W0,38h, vpmovm2q,VEX_F3_0F38_W1,38h
macro instr? dest*,src*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'mmreg' & @src.type = 'maskreg'
AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,vex_mpw,opcode>, vpmovd2m,VEX_F3_0F38_W0,39h, vpmovq2m,VEX_F3_0F38_W1,39h
macro instr? dest*,src*
AVX_512.parse_operand@dest dest
AVX_512.parse_operand@src src
if @dest.type = 'maskreg' & @src.type = 'mmreg'
AVX_512.store_instruction@src @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,opcode>, range,50h
macro v#instr#pd? dest*,src*,src2*,aux*&
AVX_512.basic_instruction_bcst_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2,aux
end macro
macro v#instr#ps? dest*,src*,src2*,aux*&
AVX_512.basic_instruction_bcst_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED+EVEX_VL,opcode,4,dest,src,src2,aux
end macro
macro v#instr#sd? dest*,src*,src2*,aux*&
AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED,opcode+1,8,dest,src,src2,aux
end macro
macro v#instr#ss? dest*,src*,src2*,aux*&
AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED,opcode+1,4,dest,src,src2,aux
end macro
end iterate
macro vreducepd? dest*,src*,aux*&
AVX_512.single_source_instruction_bcst_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED+EVEX_VL,56h,8,dest,src,aux
end macro
macro vreduceps? dest*,src*,aux*&
AVX_512.single_source_instruction_bcst_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED+EVEX_VL,56h,4,dest,src,aux
end macro
macro vreducesd? dest*,src*,src2*,aux*&
AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED,57h,8,dest,src,src2,aux
end macro
macro vreducess? dest*,src*,src2*,aux*&
AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED,57h,4,dest,src,src2,aux
end macro

View File

@ -0,0 +1,39 @@
if ~ defined AVX_512
include 'avx512f.inc'
end if
iterate <instr,unit,vex_mpw,opcode>, vexp2ps,4,VEX_66_0F38_W0,0C8h, vexp2pd,4,VEX_66_0F38_W1,0C8h, \
vrcp28ps,4,VEX_66_0F38_W0,0CAh, vrcp28pd,8,VEX_66_0F38_W1,0CAh, vrsqrt28ps,4,VEX_66_0F38_W0,0CCh, vrsqrt28pd,8,VEX_66_0F38_W1,0CCh
macro instr? dest*,src_sae*&
AVX_512.parse_k1z_operand@dest dest
match src=,sae, src_sae
AVX_512.parse_operand@src src
AVX_512.parse_sae@src sae
else
AVX_512.parse_bcst_operand@src src_sae,unit
end match
if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
if @dest.size <> 64
err 'invalid operand size'
else if @src.size and not @dest.size
err 'operand sizes do not match'
end if
AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED,opcode,@dest.mask,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
iterate <instr,unit,vex_mpw,opcode>, vrcp28ss,4,VEX_66_0F38_W0,0CBh, vrcp28sd,8,VEX_66_0F38_W1,0CBh, vrsqrt28ss,4,VEX_66_0F38_W0,0CDh, vrsqrt28sd,8,VEX_66_0F38_W1,0CDh
macro instr? dest*,src*,src2*&
AVX_512.basic_instruction vex_mpw,EVEX_REQUIRED,opcode,unit,dest,src,src2
end macro
end iterate

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,62 @@
if ~ defined AVX_512
include 'avx512f.inc'
end if
iterate <instr,postbyte>, gatherpf0,1 ,gatherpf1,2 ,scatterpf0,5, scatterpf1,6
macro v#instr#dps? src*
AVX_512.parse_k1_vsib_operand@src src
if @src.type = 'mem' & @src.mask
if @src.size and not 4 | @src.visize <> 64
err 'invalid operand size'
end if
@src.memsize = 4
AVX_512.store_instruction@src 64,VEX_66_0F38_W0,EVEX_REQUIRED,0C6h,@src.mask,postbyte,@src.index and 10000b
else
err 'invalid combination of operands'
end if
end macro
macro v#instr#qps? src*
AVX_512.parse_k1_vsib_operand@src src
if @src.type = 'mem' & @src.mask
if @src.size and not 8 | @src.visize <> 64
err 'invalid operand size'
end if
@src.memsize = 4
AVX_512.store_instruction@src 64,VEX_66_0F38_W0,EVEX_REQUIRED,0C7h,@src.mask,postbyte,@src.index and 10000b
else
err 'invalid combination of operands'
end if
end macro
macro v#instr#dpd? src*
AVX_512.parse_k1_vsib_operand@src src
if @src.type = 'mem' & @src.mask
if @src.size and not 4 | @src.visize <> 32
err 'invalid operand size'
end if
@src.memsize = 8
AVX_512.store_instruction@src 64,VEX_66_0F38_W1,EVEX_REQUIRED,0C6h,@src.mask,postbyte,@src.index and 10000b
else
err 'invalid combination of operands'
end if
end macro
macro v#instr#qpd? src*
AVX_512.parse_k1_vsib_operand@src src
if @src.type = 'mem' & @src.mask
if @src.size and not 8 | @src.visize <> 64
err 'invalid operand size'
end if
@src.memsize = 8
AVX_512.store_instruction@src 64,VEX_66_0F38_W1,EVEX_REQUIRED,0C7h,@src.mask,postbyte,@src.index and 10000b
else
err 'invalid combination of operands'
end if
end macro
end iterate

View File

@ -0,0 +1,8 @@
if ~ defined AVX_512
include 'avx512f.inc'
end if
AVX512VL = 1

View File

@ -0,0 +1,97 @@
include 'avx.inc'
macro andn? dest*,src*,src2*
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*
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*
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*
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

View File

@ -0,0 +1,106 @@
include 'bmi1.inc'
iterate <instr,opcode>, bzhi,0F5h
macro instr? dest*,src*,src2*
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*
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*
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*
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

View File

@ -0,0 +1,8 @@
iterate <instr,modrm>, endbr32,0FBh, endbr64,0FAh
macro instr?
db 0F3h,0Fh,1Eh,modrm
end macro
end iterate

View File

@ -0,0 +1,106 @@
iterate <instr,ext,postbyte>, clrssbsy,0AEh,6, rstorssp,01h,5
macro instr? src*
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*
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*
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?
db 0F3h,0Fh,01h,modrm
end macro
end iterate
iterate <instr,prefix,ext>, wrssd,0,0F6h, wrussd,66h,0F5h
macro instr? dest*,src*
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*
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

View File

@ -0,0 +1,29 @@
include 'avx.inc'
macro vcvtph2ps? dest*,src*
AVX.parse_operand@dest dest
AVX.parse_operand@src src
if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem')
if (@src.type = 'mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size*2 <> @dest.size)
err 'invalid operand size'
end if
AVX.store_instruction@src @dest.size,VEX_66_0F38_W0,13h,@dest.rm
else
err 'invalid combination of operands'
end if
end macro
macro vcvtps2ph? dest*,src*,round*
AVX.parse_operand@dest dest
AVX.parse_operand@src src
x86.parse_operand@aux round
if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm'
if (@dest.type = 'mmreg' & @dest.size <> 16) | (@dest.type = 'mem' & @dest.size*2 <> @src.size) | @aux.size and not 1
err 'invalid operand size'
end if
AVX.store_instruction@dest @src.size,VEX_66_0F3A_W0,1Dh,@src.rm,,1,@aux.imm
else
err 'invalid combination of operands'
end if
end macro

View File

@ -0,0 +1,30 @@
include 'avx.inc'
iterate <instr,lcode>, vfmaddsub,6, vfmsubadd,7, vfmadd,8, vfmsub,0Ah, vfnmadd,0Ch, vfnmsub,0Eh
iterate <order,hcode>, 132,90h, 213,0A0h, 231,0B0h
macro instr#order#pd? dest*,src*,src2*
AVX.basic_instruction VEX_66_0F38_W1,hcode+lcode,0,dest,src,src2
end macro
macro instr#order#ps? dest*,src*,src2*
AVX.basic_instruction VEX_66_0F38_W0,hcode+lcode,0,dest,src,src2
end macro
if lcode > 7
macro instr#order#sd? dest*,src*,src2*
AVX.basic_instruction VEX_66_0F38_W1,hcode+lcode+1,8,dest,src,src2
end macro
macro instr#order#ss? dest*,src*,src2*
AVX.basic_instruction VEX_66_0F38_W0,hcode+lcode+1,4,dest,src,src2
end macro
end if
end iterate
end iterate

View File

@ -0,0 +1,24 @@
iterate <instr,postbyte>, rdfsbase,0, rdgsbase,1, wrfsbase,2, wrgsbase,3
macro instr? dest*
if x86.mode = 64
x86.parse_operand@dest dest
if @dest.type = 'reg'
if @dest.size >= 4
@dest.opcode_prefix = 0F3h
x86.select_operand_prefix@dest @dest.size
x86.store_instruction@dest <0Fh,0AEh>,postbyte
else
err 'invalid operand size'
end if
else
err 'invalid operand'
end if
else
err 'instruction requires long mode'
end if
end macro
end iterate

View File

@ -0,0 +1,53 @@
include 'sse.inc'
iterate <instr,supp>, gf2p8mulb,0CFh
macro instr? dest*,src*
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*
SSE.basic_instruction_imm8 66h,<3Ah,supp>,16,dest,src,imm
end macro
end iterate
if defined AVX_512
iterate <instr,opcode>, gf2p8mulb,0CFh
macro v#instr? dest*,src*,src2*&
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*&
AVX_512.basic_instruction_bcst_imm8 VEX_66_0F3A_W1,EVEX_W1+EVEX_VL,opcode,8,dest,src,src2,imm
end macro
end iterate
else if defined AVX
iterate <instr,opcode>, gf2p8mulb,0CFh
macro v#instr? dest*,src*,src2*
AVX.basic_instruction VEX_66_0F38_W0,opcode,0,dest,src,src2
end macro
end iterate
iterate <instr,opcode>, gf2p8affineinvqb,0CFh, gf2p8affineqb,0CEh
macro v#instr? dest*,src*,src2*,imm*
AVX.basic_instruction_imm8 VEX_66_0F3A_W1,opcode,0,dest,src,src2,imm
end macro
end iterate
end if

View File

@ -0,0 +1,16 @@
macro xacquire? instr&
db 0F2h
instr
end macro
macro xrelease? instr&
db 0F3h
instr
end macro
macro xtest?
db 0Fh,1,0D6h
end macro

View File

@ -0,0 +1,15 @@
macro invpcid? dest*,src*
x86.parse_operand@dest dest
x86.parse_operand@src src
if @dest.type = 'reg' & @src.type = 'mem'
if (x86.mode < 64 & @dest.size <> 4) | (x86.mode = 64 & @dest.size <> 8) | @src.size and not 16
err 'invalid operand size'
end if
@src.opcode_prefix = 66h
x86.store_instruction@src <0Fh,38h,82h>,@dest.rm
else
err 'invalid combination of operands'
end if
end macro

View File

@ -0,0 +1,149 @@
if ~ defined MMX
restore MMX ; this ensures that symbol cannot be forward-referenced
MMX = 1
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
end namespace
end iterate
calminstruction MMX.basic_instruction ext,dest,src
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')
jno invalid_combination_of_operands
xcall x86.store_instruction@src, <0Fh,ext>,@dest.rm
exit
invalid_combination_of_operands:
err 'invalid combination of operands'
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 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 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
calminstruction MMX.bit_shift_instruction ext,dest,src
call MMX.parse_operand@dest, dest
call MMX.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 8
jno mmreg_rm_ok
err 'invalid operand size'
mmreg_rm_ok:
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
xcall x86.store_instruction@dest, <0Fh,iext>,irm,byte,@src.imm
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
macro emms?
db 0Fh,77h
end macro
end if

View File

@ -0,0 +1,23 @@
if ~ defined AVX512
define x86.dqqword? :64
define x86.zword? :64
end if
macro movdir64b? dest*,src*
x86.parse_operand@dest dest
x86.parse_operand@src src
if @dest.type = 'reg' & @src.type = 'mem'
if @src.size and not 64
err 'invalid operand size'
end if
if (@src.mode = 16 & @dest.size <> 2) | (@src.mode = 32 & @dest.size <> 4) | (@src.mode = 64 & @dest.size <> 8)
err 'invalid operand size'
end if
@src.opcode_prefix = 66h
x86.store_instruction@src <0Fh,38h,0F8h>,@dest.rm
else
err 'invalid combination of operands'
end if
end macro

View File

@ -0,0 +1,19 @@
macro movdiri? dest*,src*
x86.parse_operand@dest dest
x86.parse_operand@src src
if @src.type = 'reg' & @dest.type = 'mem'
if @dest.size <> 0 & @src.size <> @dest.size
err 'operand sizes do not match'
end if
if @src.size = 8 & x86.mode = 64
@dest.prefix = 48h
else if @src.size <> 4
err 'invalid operand size'
end if
x86.store_instruction@dest <0Fh,38h,0F9h>,@src.rm
else
err 'invalid combination of operands'
end if
end macro

View File

@ -0,0 +1,196 @@
if ~ defined MPX
restore MPX ; this ensures that symbol cannot be forward-referenced
MPX = 1
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*&
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*
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*
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*&
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*&
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
end if

View File

@ -0,0 +1,14 @@
include 'sse.inc'
macro pclmulqdq? dest*,src*,imm*
SSE.basic_instruction_imm8 66h,<3Ah,44h>,16,dest,src,imm
end macro
if defined AVX
macro vpclmulqdq? dest*,src*,src2*,imm*
AVX.basic_instruction_imm8 VEX_66_0F3A_W0,44h,16,dest,src,src2,imm
end macro
end if

View File

@ -0,0 +1,18 @@
macro ptwrite? src*
x86.parse_operand@src src
if @src.size = 0
err 'operand size not specified'
else if @src.size <> 4 & (@src.size <> 8 | x86.mode <> 64)
err 'invalid operand size'
end if
if @src.type = 'reg' | @src.type = 'mem'
if @src.size = 8
x86.select_operand_prefix@src 8
end if
@src.opcode_prefix = 0F3h
x86.store_instruction@src <0Fh,0AEh>,4
else
err 'invalid operand'
end if
end macro

View File

@ -0,0 +1,10 @@
macro rdrand? dest*
x86.parse_operand@dest dest
if @dest.type = 'reg'
x86.select_operand_prefix@dest @dest.size
x86.store_instruction@dest <0Fh,0C7h>,6
else
err 'invalid operand'
end if
end macro

View File

@ -0,0 +1,10 @@
macro rdseed? dest*
x86.parse_operand@dest dest
if @dest.type = 'reg'
x86.select_operand_prefix@dest @dest.size
x86.store_instruction@dest <0Fh,0C7h>,7
else
err 'invalid operand'
end if
end macro

View File

@ -0,0 +1,4 @@
macro rdtscp?
db 0Fh,1,0F9h
end macro

View File

@ -0,0 +1,39 @@
macro xbegin? dest*
x86.parse_jump_operand@dest dest
if @dest.type = 'imm' & ~ @dest.jump_type
if x86.mode shr 3 <> @dest.size
err 'invalid operand size'
end if
if x86.mode = 16
db 0C7h,0F8h
dw @dest.imm-($+2)
else
if ~ $ relativeto 0 & @dest.imm relativeto 0
@dest.imm = @dest.imm + $ - 0 scaleof $
err 'invalid address'
end if
if @dest.unresolved | ( @dest.imm relativeto $ & @dest.imm-($+5) < 8000h & @dest.imm-($+5) >= -8000h )
db 66h,0C7h,0F8h
dw @dest.imm-($+2)
else
db 0C7h,0F8h
dd @dest.imm-($+4)
end if
end if
else
err 'invalid operand'
end if
end macro
macro xabort? imm*
db 0C6h,0F8h,imm
end macro
macro xend?
db 0Fh,1,0D5h
end macro
macro xtest?
db 0Fh,1,0D6h
end macro

View File

@ -0,0 +1,4 @@
macro getsec?
db 0Fh,37h
end macro

View File

@ -0,0 +1,433 @@
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

View File

@ -0,0 +1,603 @@
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

View File

@ -0,0 +1,72 @@
include 'sse2.inc'
macro fisttp? src*
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*
SSE.basic_instruction 66h,ext,16,dest,src
end macro
macro instr#ps? dest*,src*
SSE.basic_instruction 0F2h,ext,16,dest,src
end macro
end iterate
iterate <instr,ext>, movsldup,12h, movshdup,16h
macro instr? dest*,src*
SSE.basic_instruction 0F3h,ext,16,dest,src
end macro
end iterate
macro movddup? dest*,src*
SSE.basic_instruction 0F2h,12h,8,dest,src
end macro
macro lddqu? dest*,src*
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
macro monitor? arg1,arg2,arg3
match any, arg1 arg2 arg3
if ~ arg1 eq eax | ~ arg2 eq ecx | ~ arg3 eq edx
err 'invalid combination of operands'
end if
end match
db 0Fh,01h,0C8h
end macro
macro mwait? arg1,arg2
match any, arg1 arg2
if ~ arg1 eq eax | ~ arg2 eq ecx
err 'invalid combination of operands'
end if
end match
db 0Fh,01h,0C9h
end macro

View File

@ -0,0 +1,204 @@
include 'ssse3.inc'
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*
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*
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*
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*
SSE.basic_instruction 66h,<38h,20h+code>,msize,dest,src
end macro
macro pmovzx#conv? dest*,src*
SSE.basic_instruction 66h,<38h,30h+code>,msize,dest,src
end macro
end iterate
macro insertps? dest*,src*,sel*
SSE.basic_instruction_imm8 66h,<3Ah,21h>,4,dest,src,sel
end macro
macro extractps? 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 | @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*
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*
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*
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*
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*
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*
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*
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*
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

View File

@ -0,0 +1,54 @@
include 'sse4.1.inc'
iterate <instr,supp>, pcmpgtq,37h
macro instr? dest*,src*
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*
SSE.basic_instruction_imm8 66h,<3Ah,supp>,16,dest,src,imm
end macro
end iterate
macro crc32? dest*,src*
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*
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

View File

@ -0,0 +1,26 @@
include 'sse3.inc'
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*
MMX.basic_instruction <38h,supp>,dest,src
end macro
end iterate
macro palignr? dest*,src*,aux*
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

View File

@ -0,0 +1,37 @@
include 'aes.inc'
if defined AVX_512
iterate <instr,opcode>, aesenc,0DCh, aesenclast,0DDh, aesdec,0DEh, aesdeclast,0DFh
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
AVX_512.store_instruction@src2 @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,0,@dest.rm,@src.rm
else
err 'invalid combination of operands'
end if
end macro
end iterate
else
include 'avx.inc'
iterate <instr,opcode>, aesenc,0DCh, aesenclast,0DDh, aesdec,0DEh, aesdeclast,0DFh
macro v#instr? dest*,src*,src2*
AVX.basic_instruction VEX_66_0F38_W0,opcode,0,dest,src,src2
end macro
end iterate
end if

View File

@ -0,0 +1,65 @@
iterate <instr,prefix,ext,postbyte>, vmxon,0F3h,0C7h,6, vmclear,66h,0C7h,6, \
vmptrld,0,0C7h,6, vmptrst,0,0C7h,7
macro instr? src*
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?
db 0Fh,1,0C4h
end macro
macro vmcall?
db 0Fh,1,0C1h
end macro
macro vmlaunch?
db 0Fh,1,0C2h
end macro
macro vmresume?
db 0Fh,1,0C3h
end macro
macro vmread? dest*,src*
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*
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

View File

@ -0,0 +1,32 @@
include 'pclmulqdq.inc'
if defined AVX_512
macro vpclmulqdq? dest*,src*,src2*,aux*
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
else
include 'avx.inc'
macro vpclmulqdq? dest*,src*,src2*,imm*
AVX.basic_instruction_imm8 VEX_66_0F3A_W0,44h,0,dest,src,src2,imm
end macro
end if

View File

@ -0,0 +1,35 @@
iterate <instr,postbyte>, xsave,4, xrstor,5
macro instr? src*
x86.parse_operand@src src
if @src.type = 'mem'
x86.store_instruction@src <0Fh,0AEh>,postbyte
else
err 'invalid operand'
end if
end macro
macro instr#64? src*
if x86.mode = 64
x86.parse_operand@src src
if @src.type = 'mem'
x86.select_operand_prefix@src 8
x86.store_instruction@src <0Fh,0AEh>,postbyte
else
err 'invalid operand'
end if
else
err 'instruction requires long mode'
end if
end macro
end iterate
macro xgetbv?
db 0Fh,1,0D0h
end macro
macro xsetbv?
db 0Fh,1,0D1h
end macro

View File

@ -0,0 +1,470 @@
macro struct? name
macro end?.struct?!
end namespace
esc end struc
virtual at 0
name name
sizeof.name = $
end virtual
purge end?.struct?
end macro
esc struc name
label . : sizeof.name
namespace .
end macro
struct SCNHDR
s_name db 8 dup ?
s_paddr dd ?
s_vaddr dd ?
s_size dd ?
s_scnptr dd ?
s_relptr dd ?
s_lnnoptr dd ?
s_nreloc dw ?
s_nlnno dw ?
s_flags dd ?
end struct
SCNHSZ = sizeof SCNHDR
struct RELOC
r_vaddr dd ?
r_symndx dd ?
r_type dw ?
end struct
RELSZ = sizeof RELOC
struct SYMENT
e_name db 8 dup ?
virtual at e_name
e_zeroes dd ?
e_offset dd ?
end virtual
e_value dd ?
e_scnum dw ?
e_type dw ?
e_sclass db ?
e_numaux db ?
end struct
SYMESZ = sizeof SYMENT
I386MAGIC = 0x14c
F_RELFLG = 0x0001
F_EXEC = 0x0002
F_LNNO = 0x0004
F_LSYMS = 0x0008
F_AR32WR = 0x0100
STYP_TEXT = 0x0020
STYP_DATA = 0x0040
STYP_BSS = 0x0080
N_UNDEF = 0
N_ABS = -1
N_DEBUG = -2
T_NULL = 0000b
T_VOID = 0001b
T_CHAR = 0010b
T_SHORT = 0011b
T_INT = 0100b
T_LONG = 0101b
T_FLOAT = 0110b
T_DOUBLE = 0111b
T_STRUCT = 1000b
T_UNION = 1001b
T_ENUM = 1010b
T_MOE = 1011b
T_UCHAR = 1100b
T_USHORT = 1101b
T_UINT = 1110b
T_ULONG = 1111b
T_LNGDBL = 01_0000b
DT_NON = 00b
DT_PTR = 01b
DT_FCN = 10b
DT_ARY = 11b
C_NULL = 0
C_AUTO = 1
C_EXT = 2
C_STAT = 3
C_REG = 4
C_EXTDEF = 5
C_LABEL = 6
C_ULABEL = 7
C_MOS = 8
C_ARG = 9
C_STRTAG = 10
C_MOU = 11
C_UNTAG = 12
C_TPDEF = 13
C_USTATIC = 14
C_ENTAG = 15
C_MOE = 16
C_REGPARM = 17
C_FIELD = 18
C_AUTOARG = 19
C_LASTENT = 20
C_BLOCK = 100
C_FCN = 101
C_EOS = 102
C_FILE = 103
C_LINE = 104
C_ALIAS = 105
C_HIDDEN = 106
C_EFCN = 255
RELOC_ADDR32 = 6
RELOC_REL32 = 20
COFF::
namespace COFF
Header:
f_magic dw I386MAGIC
f_nscns dw NUMBER_OF_SECTIONS
f_timdat dd __TIME__
f_symptr dd SYMBOL_TABLE_OFFSET
f_nsyms dd NUMBER_OF_SYMBOLS
f_opthdr dw 0
f_flags dw F_AR32WR + F_LNNO
Sections: db NUMBER_OF_SECTIONS * SCNHSZ dup 0
virtual at 0
symbol_table:: rb NUMBER_OF_SYMBOLS * SYMESZ
end virtual
virtual at 0
string_table:: dd STRING_TABLE_SIZE
STRING_POSITION = $
rb STRING_TABLE_SIZE - $
end virtual
virtual at 0
relocations:: rb NUMBER_OF_RELOCATIONS * RELSZ
end virtual
element relocatable?
macro section_start
local sym
element sym : relocatable * (1+SECTION_INDEX) + SYMBOL_INDEX
SECTION_BASE = sym
org sym
if DEFINED_SECTION | defined DEFAULT_SECTION
store SECTION_NAME : 8 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_name
store C_STAT at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_sclass
store 1+SECTION_INDEX at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_scnum
SYMBOL_INDEX = SYMBOL_INDEX + 1
end if
end macro
RELOCATION_INDEX = 0
SECTION_INDEX = 0
SECTION_RELOCATION_INDEX = RELOCATION_INDEX
SYMBOL_INDEX = 0
SECTION_OFFSET = $%
SECTION_ALIGN = 4
SECTION_NAME = '.flat'
SECTION_FLAGS = STYP_TEXT + STYP_DATA
DEFINED_SECTION = 0
section_start
end namespace
macro section?
namespace COFF
SECTION_SIZE = $% - SECTION_OFFSET
if DEFINED_SECTION | SECTION_SIZE > 0
if ~ DEFINED_SECTION
DEFAULT_SECTION := 1
end if
if $%% = SECTION_OFFSET
SECTION_FLAGS = SECTION_FLAGS or STYP_BSS
SECTION_OFFSET = 0
section $
else
UNINITIALIZED_LENGTH = $% - $%%
section $
db UNINITIALIZED_LENGTH dup 0
end if
store SECTION_NAME : 8 at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_name
store SECTION_OFFSET at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_scnptr
store SECTION_SIZE at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_size
store SECTION_FLAGS at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_flags
if RELOCATION_INDEX > SECTION_RELOCATION_INDEX
store RELOCATION_INDEX - SECTION_RELOCATION_INDEX at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_nreloc
store RELOCATIONS_OFFSET + SECTION_RELOCATION_INDEX * RELSZ at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_relptr
end if
SECTION_INDEX = SECTION_INDEX + 1
end if
end namespace
end macro
macro section? declaration*
namespace COFF
section
DEFINED_SECTION = 1
SECTION_FLAGS = 0
SECTION_OFFSET = $%
SECTION_ALIGN = 4
match name attributes, declaration
SECTION_NAME = name
local seq,list
define seq attributes
while 1
match car cdr, seq
define list car
define seq cdr
else
match any, seq
define list any
end match
break
end match
end while
irpv attribute, list
match =code?, attribute
SECTION_FLAGS = SECTION_FLAGS or STYP_TEXT
else match =data?, attribute
SECTION_FLAGS = SECTION_FLAGS or STYP_DATA
else
err 'unknown attribute "',`attribute,'"'
end match
end irpv
else
SECTION_NAME = declaration
end match
section_start
SECTION_RELOCATION_INDEX = RELOCATION_INDEX
end namespace
end macro
calminstruction align? boundary,value:?
check COFF.SECTION_ALIGN mod (boundary) = 0
jyes allowed
err 'section not aligned enough'
exit
allowed:
compute boundary, (boundary-1)-($-COFF.SECTION_BASE+boundary-1) mod boundary
arrange value, =db boundary =dup value
assemble value
end calminstruction
macro public? declaration*
namespace COFF
match =static? value =as? str, declaration
SYMBOL_VALUE = value
SYMBOL_NAME = string str
SYMBOL_CLASS = C_STAT
else match value =as? str, declaration
SYMBOL_VALUE = value
SYMBOL_NAME = string str
SYMBOL_CLASS = C_EXT
else match =static? value, declaration
SYMBOL_VALUE = value
SYMBOL_NAME = `value
SYMBOL_CLASS = C_STAT
else
SYMBOL_VALUE = declaration
SYMBOL_NAME = `declaration
SYMBOL_CLASS = C_EXT
end match
if SYMBOL_VALUE relativeto 1 elementof SYMBOL_VALUE & 1 elementof (1 metadataof SYMBOL_VALUE) relativeto relocatable & 1 scaleof (1 metadataof SYMBOL_VALUE) > 0
SYMBOL_SECTION_INDEX = 1 scaleof (1 metadataof SYMBOL_VALUE)
SYMBOL_VALUE = SYMBOL_VALUE - 1 elementof SYMBOL_VALUE
else
SYMBOL_SECTION_INDEX = N_ABS
end if
if lengthof SYMBOL_NAME > 8
store 0 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_zeroes
store STRING_POSITION at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_offset
store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION
STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1
else
store SYMBOL_NAME : 8 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_name
end if
store SYMBOL_VALUE at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_value
store SYMBOL_SECTION_INDEX at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_scnum
store SYMBOL_CLASS at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_sclass
SYMBOL_INDEX = SYMBOL_INDEX + 1
end namespace
end macro
macro extrn? declaration*
namespace COFF
local sym,psym
element sym : relocatable * (-1) + SYMBOL_INDEX
match str =as? name:size, declaration
label name:size at sym
SYMBOL_NAME = string str
else match name:size, declaration
label name:size at sym
SYMBOL_NAME = `name
else match str =as? name, declaration
label name at sym
SYMBOL_NAME = string str
else
label declaration at sym
SYMBOL_NAME = `declaration
end match
if lengthof SYMBOL_NAME > 8
store 0 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_zeroes
store STRING_POSITION at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_offset
store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION
STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1
else
store SYMBOL_NAME : 8 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_name
end if
store C_EXT at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_sclass
SYMBOL_INDEX = SYMBOL_INDEX + 1
end namespace
end macro
calminstruction calminstruction?.initsym? var*, val&
publish var, val
end calminstruction
calminstruction calminstruction?.asm? line&
local name, i
initsym name, name.0
match name.i, name
compute i, i+1
arrange name, name.i
publish name, line
arrange line, =assemble name
assemble line
end calminstruction
calminstruction dword? value
compute value, value
check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto COFF.relocatable
jyes addr32
check ~ value relativeto 0 & (value + COFF.SECTION_BASE) relativeto 1 elementof (value + COFF.SECTION_BASE)
jno plain
check 1 elementof (1 metadataof (value + COFF.SECTION_BASE)) relativeto COFF.relocatable
jyes rel32
plain:
emit 4, value
exit
local offset, symndx, type
addr32:
compute symndx, 0 scaleof (1 metadataof value)
compute type, RELOC_ADDR32
jump add_relocation
rel32:
compute value, value + COFF.SECTION_BASE
compute symndx, 0 scaleof (1 metadataof value)
compute type, RELOC_REL32
jump add_relocation
add_relocation:
compute offset, $%
emit 4, 0 scaleof value
check $% > offset
jno done
compute offset, offset - COFF.SECTION_OFFSET
local reloc
compute reloc, COFF.RELOCATION_INDEX * RELSZ
asm store offset at COFF.relocations : reloc + RELOC.r_vaddr
asm store symndx at COFF.relocations : reloc + RELOC.r_symndx
asm store type at COFF.relocations : reloc + RELOC.r_type
compute COFF.RELOCATION_INDEX, COFF.RELOCATION_INDEX + 1
done:
end calminstruction
calminstruction dd? definitions&
local value, n
start:
match value=,definitions, definitions, ()
jyes recognize
match value, definitions
arrange definitions,
recognize:
match n =dup? value, value, ()
jyes duplicate
match ?, value
jyes reserve
call dword, value
next:
match , definitions
jno start
take , definitions
take definitions, definitions
jyes next
exit
reserve:
emit dword
jump next
duplicate:
match (value), value
stack:
check n
jno next
take definitions, value
arrange value, definitions
compute n, n - 1
jump stack
end calminstruction
calminstruction (label) dd? definitions&
local cmd
arrange cmd, =label label : =dword
assemble cmd
arrange cmd, =dd definitions
assemble cmd
end calminstruction
postpone
purge section?
section
namespace COFF
NUMBER_OF_SECTIONS := SECTION_INDEX
STRING_TABLE_SIZE := STRING_POSITION
NUMBER_OF_SYMBOLS := SYMBOL_INDEX
NUMBER_OF_RELOCATIONS := RELOCATION_INDEX
RELOCATIONS_OFFSET = $%
load byte_sequence : NUMBER_OF_RELOCATIONS * RELSZ from relocations:0
db byte_sequence
SYMBOL_TABLE_OFFSET = $%
load byte_sequence : NUMBER_OF_SYMBOLS * SYMESZ from symbol_table:0
db byte_sequence
load byte_sequence : STRING_TABLE_SIZE from string_table:0
db byte_sequence
end namespace
end postpone

View File

@ -0,0 +1,754 @@
macro struct? name
macro end?.struct?!
end namespace
esc end struc
virtual at 0
name name
sizeof.name = $
end virtual
purge end?.struct?
end macro
esc struc name
label . : sizeof.name
namespace .
end macro
struct IMAGE_SECTION_HEADER
Name db 8 dup ?
VirtualSize dd ?
VirtualAddress dd ?
SizeOfRawData dd ?
PointerToRawData dd ?
PointerToRelocations dd ?
PointerToLinenumbers dd ?
NumberOfRelocations dw ?
NumberOfLinenumbers dw ?
Characteristics dd ?
end struct
struct IMAGE_RELOCATION
VirtualAddress dd ?
SymbolTableIndex dd ?
Type dw ?
end struct
struct IMAGE_SYMBOL
ShortName db 8 dup ?
virtual at ShortName
Zeroes dd ?
Offset dd ?
end virtual
Value dd ?
SectionNumber dw ?
Type dw ?
StorageClass db ?
NumberOfAuxSymbols db ?
end struct
IMAGE_FILE_MACHINE_UNKNOWN = 0x0
IMAGE_FILE_MACHINE_AM33 = 0x1D3
IMAGE_FILE_MACHINE_AMD64 = 0x8664
IMAGE_FILE_MACHINE_ARM = 0x1C0
IMAGE_FILE_MACHINE_ARMNT = 0x1C4
IMAGE_FILE_MACHINE_ARM64 = 0xAA64
IMAGE_FILE_MACHINE_EBC = 0xEBC
IMAGE_FILE_MACHINE_I386 = 0x14C
IMAGE_FILE_MACHINE_IA64 = 0x200
IMAGE_FILE_MACHINE_M32R = 0x9041
IMAGE_FILE_MACHINE_MIPS16 = 0x266
IMAGE_FILE_MACHINE_MIPSFPU = 0x366
IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466
IMAGE_FILE_MACHINE_POWERPC = 0x1F0
IMAGE_FILE_MACHINE_POWERPCFP = 0x1F1
IMAGE_FILE_MACHINE_R4000 = 0x166
IMAGE_FILE_MACHINE_SH3 = 0x1A2
IMAGE_FILE_MACHINE_SH3DSP = 0x1A3
IMAGE_FILE_MACHINE_SH4 = 0x1A6
IMAGE_FILE_MACHINE_SH5 = 0x1A8
IMAGE_FILE_MACHINE_THUMB = 0x1C2
IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169
IMAGE_FILE_RELOCS_STRIPPED = 0x0001
IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002
IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004
IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008
IMAGE_FILE_AGGRESSIVE_WS_TRIM = 0x0010
IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020
IMAGE_FILE_BYTES_REVERSED_LO = 0x0080
IMAGE_FILE_32BIT_MACHINE = 0x0100
IMAGE_FILE_DEBUG_STRIPPED = 0x0200
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400
IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800
IMAGE_FILE_SYSTEM = 0x1000
IMAGE_FILE_DLL = 0x2000
IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000
IMAGE_FILE_BYTES_REVERSED_HI = 0x8000
IMAGE_SCN_TYPE_NO_PAD = 0x00000008
IMAGE_SCN_CNT_CODE = 0x00000020
IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040
IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
IMAGE_SCN_LNK_OTHER = 0x00000100
IMAGE_SCN_LNK_INFO = 0x00000200
IMAGE_SCN_LNK_REMOVE = 0x00000800
IMAGE_SCN_LNK_COMDAT = 0x00001000
IMAGE_SCN_GPREL = 0x00008000
IMAGE_SCN_MEM_PURGEABLE = 0x00020000
IMAGE_SCN_MEM_16BIT = 0x00020000
IMAGE_SCN_MEM_LOCKED = 0x00040000
IMAGE_SCN_MEM_PRELOAD = 0x00080000
IMAGE_SCN_ALIGN_1BYTES = 0x00100000
IMAGE_SCN_ALIGN_2BYTES = 0x00200000
IMAGE_SCN_ALIGN_4BYTES = 0x00300000
IMAGE_SCN_ALIGN_8BYTES = 0x00400000
IMAGE_SCN_ALIGN_16BYTES = 0x00500000
IMAGE_SCN_ALIGN_32BYTES = 0x00600000
IMAGE_SCN_ALIGN_64BYTES = 0x00700000
IMAGE_SCN_ALIGN_128BYTES = 0x00800000
IMAGE_SCN_ALIGN_256BYTES = 0x00900000
IMAGE_SCN_ALIGN_512BYTES = 0x00A00000
IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000
IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000
IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000
IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000
IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000
IMAGE_SCN_MEM_DISCARDABLE = 0x02000000
IMAGE_SCN_MEM_NOT_CACHED = 0x04000000
IMAGE_SCN_MEM_NOT_PAGED = 0x08000000
IMAGE_SCN_MEM_SHARED = 0x10000000
IMAGE_SCN_MEM_EXECUTE = 0x20000000
IMAGE_SCN_MEM_READ = 0x40000000
IMAGE_SCN_MEM_WRITE = 0x80000000
IMAGE_REL_AMD64_ABSOLUTE = 0x0000
IMAGE_REL_AMD64_ADDR64 = 0x0001
IMAGE_REL_AMD64_ADDR32 = 0x0002
IMAGE_REL_AMD64_ADDR32NB = 0x0003
IMAGE_REL_AMD64_REL32 = 0x0004
IMAGE_REL_AMD64_REL32_1 = 0x0005
IMAGE_REL_AMD64_REL32_2 = 0x0006
IMAGE_REL_AMD64_REL32_3 = 0x0007
IMAGE_REL_AMD64_REL32_4 = 0x0008
IMAGE_REL_AMD64_REL32_5 = 0x0009
IMAGE_REL_AMD64_SECTION = 0x000A
IMAGE_REL_AMD64_SECREL = 0x000B
IMAGE_REL_AMD64_SECREL7 = 0x000C
IMAGE_REL_AMD64_TOKEN = 0x000D
IMAGE_REL_AMD64_SREL32 = 0x000E
IMAGE_REL_AMD64_PAIR = 0x000F
IMAGE_REL_AMD64_SSPAN32 = 0x0010
IMAGE_REL_I386_ABSOLUTE = 0x0000
IMAGE_REL_I386_DIR16 = 0x0001
IMAGE_REL_I386_REL16 = 0x0002
IMAGE_REL_I386_DIR32 = 0x0006
IMAGE_REL_I386_DIR32NB = 0x0007
IMAGE_REL_I386_SEG12 = 0x0009
IMAGE_REL_I386_SECTION = 0x000A
IMAGE_REL_I386_SECREL = 0x000B
IMAGE_REL_I386_TOKEN = 0x000C
IMAGE_REL_I386_SECREL7 = 0x000D
IMAGE_REL_I386_REL32 = 0x0014
IMAGE_SYM_UNDEFINED = 0
IMAGE_SYM_ABSOLUTE = -1
IMAGE_SYM_DEBUG = -2
IMAGE_SYM_TYPE_NULL = 0
IMAGE_SYM_TYPE_VOID = 1
IMAGE_SYM_TYPE_CHAR = 2
IMAGE_SYM_TYPE_SHORT = 3
IMAGE_SYM_TYPE_INT = 4
IMAGE_SYM_TYPE_LONG = 5
IMAGE_SYM_TYPE_FLOAT = 6
IMAGE_SYM_TYPE_DOUBLE = 7
IMAGE_SYM_TYPE_STRUCT = 8
IMAGE_SYM_TYPE_UNION = 9
IMAGE_SYM_TYPE_ENUM = 10
IMAGE_SYM_TYPE_MOE = 11
IMAGE_SYM_TYPE_BYTE = 12
IMAGE_SYM_TYPE_WORD = 13
IMAGE_SYM_TYPE_UINT = 14
IMAGE_SYM_TYPE_DWORD = 15
IMAGE_SYM_DTYPE_NULL = 0
IMAGE_SYM_DTYPE_POINTER = 1
IMAGE_SYM_DTYPE_FUNCTION = 2
IMAGE_SYM_DTYPE_ARRAY = 3
IMAGE_SYM_CLASS_END_OF_FUNCTION = -1
IMAGE_SYM_CLASS_NULL = 0
IMAGE_SYM_CLASS_AUTOMATIC = 1
IMAGE_SYM_CLASS_EXTERNAL = 2
IMAGE_SYM_CLASS_STATIC = 3
IMAGE_SYM_CLASS_REGISTER = 4
IMAGE_SYM_CLASS_EXTERNAL_DEF = 5
IMAGE_SYM_CLASS_LABEL = 6
IMAGE_SYM_CLASS_UNDEFINED_LABEL = 7
IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 8
IMAGE_SYM_CLASS_ARGUMENT = 9
IMAGE_SYM_CLASS_STRUCT_TAG = 10
IMAGE_SYM_CLASS_MEMBER_OF_UNION = 11
IMAGE_SYM_CLASS_UNION_TAG = 12
IMAGE_SYM_CLASS_TYPE_DEFINITION = 13
IMAGE_SYM_CLASS_UNDEFINED_STATIC = 14
IMAGE_SYM_CLASS_ENUM_TAG = 15
IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 16
IMAGE_SYM_CLASS_REGISTER_PARAM = 17
IMAGE_SYM_CLASS_BIT_FIELD = 18
IMAGE_SYM_CLASS_BLOCK = 100
IMAGE_SYM_CLASS_FUNCTION = 101
IMAGE_SYM_CLASS_END_OF_STRUCT = 102
IMAGE_SYM_CLASS_FILE = 103
IMAGE_SYM_CLASS_SECTION = 104
IMAGE_SYM_CLASS_WEAK_EXTERNAL = 105
IMAGE_SYM_CLASS_CLR_TOKEN = 107
IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY = 1
IMAGE_WEAK_EXTERN_SEARCH_LIBRARY = 2
IMAGE_WEAK_EXTERN_SEARCH_ALIAS = 3
COFF::
namespace COFF
if defined Settings.Machine
MACHINE := Settings.Machine
else
MACHINE := IMAGE_FILE_MACHINE_I386
end if
if defined Settings.Characteristics
CHARACTERISTICS = Settings.Characteristics
else
CHARACTERISTICS = IMAGE_FILE_32BIT_MACHINE
end if
Header:
Machine dw MACHINE
NumberOfSections dw NUMBER_OF_SECTIONS
TimeDateStamp dd __TIME__
PointerToSymbolTable dd SYMBOL_TABLE_OFFSET
NumberOfSymbols dd NUMBER_OF_SYMBOLS
SizeOfOptionalHeader dw 0
Characteristics dw CHARACTERISTICS
Sections: db NUMBER_OF_SECTIONS * sizeof IMAGE_SECTION_HEADER dup 0
virtual at 0
symbol_table:: rb NUMBER_OF_SYMBOLS * sizeof IMAGE_SYMBOL
end virtual
virtual at 0
string_table:: dd STRING_TABLE_SIZE
STRING_POSITION = $
rb STRING_TABLE_SIZE - $
end virtual
virtual at 0
relocations:: rb NUMBER_OF_RELOCATIONS * sizeof IMAGE_RELOCATION
end virtual
element relocatable?
macro section_start
local sym
element sym : relocatable * (1+SECTION_INDEX) + SYMBOL_INDEX
SECTION_BASE = sym
org sym
if DEFINED_SECTION | defined DEFAULT_SECTION
store SECTION_NAME : 8 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.ShortName
store IMAGE_SYM_CLASS_STATIC at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.StorageClass
store 1+SECTION_INDEX at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.SectionNumber
SYMBOL_INDEX = SYMBOL_INDEX + 1
end if
end macro
RELOCATION_INDEX = 0
SECTION_INDEX = 0
SECTION_RELOCATION_INDEX = RELOCATION_INDEX
SYMBOL_INDEX = 0
SECTION_OFFSET = $%
SECTION_ALIGN = 4
SECTION_NAME = '.flat'
SECTION_FLAGS = IMAGE_SCN_CNT_CODE + IMAGE_SCN_CNT_INITIALIZED_DATA
DEFINED_SECTION = 0
section_start
end namespace
macro section?
namespace COFF
SECTION_SIZE = $% - SECTION_OFFSET
if DEFINED_SECTION | SECTION_SIZE > 0
if ~ DEFINED_SECTION
DEFAULT_SECTION := 1
end if
if $%% = SECTION_OFFSET
SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_CNT_UNINITIALIZED_DATA
SECTION_OFFSET = 0
section $
else
UNINITIALIZED_LENGTH = $% - $%%
section $
db UNINITIALIZED_LENGTH dup 0
end if
if RELOCATION_INDEX > SECTION_RELOCATION_INDEX
store RELOCATIONS_OFFSET + SECTION_RELOCATION_INDEX * sizeof IMAGE_RELOCATION at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.PointerToRelocations
if RELOCATION_INDEX - SECTION_RELOCATION_INDEX > 65535
SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_LNK_NRELOC_OVFL
store 0FFFFh at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.NumberOfRelocations
load RELOCATIONS : (RELOCATION_INDEX - SECTION_RELOCATION_INDEX) * sizeof IMAGE_RELOCATION from relocations : SECTION_RELOCATION_INDEX * sizeof IMAGE_RELOCATION
store RELOCATIONS : (RELOCATION_INDEX - SECTION_RELOCATION_INDEX) * sizeof IMAGE_RELOCATION at relocations : (SECTION_RELOCATION_INDEX+1) * sizeof IMAGE_RELOCATION
RELOCATION_INDEX = RELOCATION_INDEX + 1
store RELOCATION_INDEX - SECTION_RELOCATION_INDEX at relocations : SECTION_RELOCATION_INDEX * sizeof IMAGE_RELOCATION + IMAGE_RELOCATION.VirtualAddress
store 0 at relocations : SECTION_RELOCATION_INDEX * sizeof IMAGE_RELOCATION + IMAGE_RELOCATION.SymbolTableIndex
store 0 at relocations : SECTION_RELOCATION_INDEX * sizeof IMAGE_RELOCATION + IMAGE_RELOCATION.Type
else
store RELOCATION_INDEX - SECTION_RELOCATION_INDEX at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.NumberOfRelocations
end if
end if
store SECTION_NAME : 8 at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.Name
store SECTION_OFFSET at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.PointerToRawData
store SECTION_SIZE at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.SizeOfRawData
store SECTION_FLAGS at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.Characteristics
SECTION_INDEX = SECTION_INDEX + 1
end if
end namespace
end macro
macro section? declaration*
namespace COFF
section
DEFINED_SECTION = 1
SECTION_FLAGS = 0
SECTION_OFFSET = $%
SECTION_ALIGN = 4
match name attributes, declaration
SECTION_NAME = name
local seq,list
match flags =align? boundary, attributes
SECTION_ALIGN = boundary
define seq flags
else match =align? boundary, attributes
SECTION_ALIGN = boundary
define seq
else
define seq attributes
end match
while 1
match car cdr, seq
define list car
define seq cdr
else
match any, seq
define list any
end match
break
end match
end while
irpv attribute, list
match =code?, attribute
SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_CNT_CODE
else match =data?, attribute
SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_CNT_INITIALIZED_DATA
else match =readable?, attribute
SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_MEM_READ
else match =writeable?, attribute
SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_MEM_WRITE
else match =executable?, attribute
SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_MEM_EXECUTE
else match =shareable?, attribute
SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_MEM_SHARED
else match =discardable?, attribute
SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_MEM_DISCARDABLE
else match =notpageable?, attribute
SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_MEM_NOT_PAGED
else match =linkremove?, attribute
SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_LNK_REMOVE
else match =linkinfo?, attribute
SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_LNK_INFO
else
err 'unknown attribute "',`attribute,'"'
end match
end irpv
else
SECTION_NAME = declaration
end match
repeat 1, i:SECTION_ALIGN
if defined IMAGE_SCN_ALIGN_#i#BYTES
SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_ALIGN_#i#BYTES
else
err 'invalid section alignment'
end if
end repeat
section_start
SECTION_RELOCATION_INDEX = RELOCATION_INDEX
end namespace
end macro
calminstruction align? boundary,value:?
check COFF.SECTION_ALIGN mod (boundary) = 0
jyes allowed
err 'section not aligned enough'
exit
allowed:
compute boundary, (boundary-1)-($-COFF.SECTION_BASE+boundary-1) mod boundary
arrange value, =db boundary =dup value
assemble value
end calminstruction
macro public? declaration*
namespace COFF
match =static? value =as? str, declaration
SYMBOL_VALUE = value
SYMBOL_NAME = string str
SYMBOL_CLASS = IMAGE_SYM_CLASS_STATIC
else match value =as? str, declaration
SYMBOL_VALUE = value
SYMBOL_NAME = string str
SYMBOL_CLASS = IMAGE_SYM_CLASS_EXTERNAL
else match =static? value, declaration
SYMBOL_VALUE = value
SYMBOL_NAME = `value
SYMBOL_CLASS = IMAGE_SYM_CLASS_STATIC
else
SYMBOL_VALUE = declaration
SYMBOL_NAME = `declaration
SYMBOL_CLASS = IMAGE_SYM_CLASS_EXTERNAL
end match
if SYMBOL_VALUE relativeto 1 elementof SYMBOL_VALUE & 1 elementof (1 metadataof SYMBOL_VALUE) relativeto relocatable & SYMBOL_CLASS = IMAGE_SYM_CLASS_EXTERNAL
if 1 scaleof (1 metadataof SYMBOL_VALUE) > 0
SYMBOL_SECTION_INDEX = 1 scaleof (1 metadataof SYMBOL_VALUE)
SYMBOL_VALUE = SYMBOL_VALUE - 1 elementof SYMBOL_VALUE
else
SYMBOL_SECTION_INDEX = IMAGE_SYM_UNDEFINED
SYMBOL_VALUE = 0
SYMBOL_CLASS = IMAGE_SYM_CLASS_WEAK_EXTERNAL
SYMBOL_TAG = 0 scaleof (1 metadataof SYMBOL_VALUE)
end if
else
SYMBOL_SECTION_INDEX = IMAGE_SYM_ABSOLUTE
end if
if lengthof SYMBOL_NAME > 8
store 0 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.Zeroes
store STRING_POSITION at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.Offset
store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION
STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1
else
store SYMBOL_NAME : 8 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.ShortName
end if
store SYMBOL_VALUE at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.Value
store SYMBOL_SECTION_INDEX at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.SectionNumber
store SYMBOL_CLASS at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.StorageClass
if SYMBOL_CLASS = IMAGE_SYM_CLASS_WEAK_EXTERNAL
store 1 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.NumberOfAuxSymbols
SYMBOL_INDEX = SYMBOL_INDEX + 1
store SYMBOL_TAG : 4 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL
store IMAGE_WEAK_EXTERN_SEARCH_ALIAS : 4 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + 4
end if
SYMBOL_INDEX = SYMBOL_INDEX + 1
end namespace
end macro
macro extrn? declaration*
namespace COFF
local sym,psym
element sym : relocatable * (-1) + SYMBOL_INDEX
match str =as? name:size, declaration
label name:size at sym
SYMBOL_NAME = string str
else match name:size, declaration
label name:size at sym
SYMBOL_NAME = `name
else match str =as? name, declaration
label name at sym
SYMBOL_NAME = string str
else
label declaration at sym
SYMBOL_NAME = `declaration
end match
if lengthof SYMBOL_NAME > 8
store 0 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.Zeroes
store STRING_POSITION at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.Offset
store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION
STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1
else
store SYMBOL_NAME : 8 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.ShortName
end if
store IMAGE_SYM_CLASS_EXTERNAL at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.StorageClass
SYMBOL_INDEX = SYMBOL_INDEX + 1
end namespace
end macro
element COFF.IMAGE_BASE
RVA? equ -COFF.IMAGE_BASE+
calminstruction calminstruction?.initsym? var*, val&
publish var, val
end calminstruction
calminstruction calminstruction?.asm? line&
local name, i
initsym name, name.0
match name.i, name
compute i, i+1
arrange name, name.i
publish name, line
arrange line, =assemble name
assemble line
end calminstruction
if COFF.MACHINE = IMAGE_FILE_MACHINE_I386
calminstruction dword? value
compute value, value
check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto COFF.relocatable
jyes dir32
check ~ value relativeto 0 & (value + COFF.IMAGE_BASE) relativeto 1 elementof (value + COFF.IMAGE_BASE) & 1 elementof (1 metadataof (value + COFF.IMAGE_BASE)) relativeto COFF.relocatable
jyes dir32nb
check ~ value relativeto 0 & (value + COFF.SECTION_BASE) relativeto 1 elementof (value + COFF.SECTION_BASE)
jno plain
check 1 elementof (1 metadataof (value + COFF.SECTION_BASE)) relativeto COFF.relocatable
jyes rel32
plain:
emit 4, value
exit
local offset, symndx, type
dir32:
compute symndx, 0 scaleof (1 metadataof value)
compute type, IMAGE_REL_I386_DIR32
jump add_relocation
dir32nb:
compute value, value + COFF.IMAGE_BASE
compute symndx, 0 scaleof (1 metadataof value)
compute type, IMAGE_REL_I386_DIR32NB
jump add_relocation
rel32:
compute value, value + (COFF.SECTION_BASE + $% + 4 - COFF.SECTION_OFFSET)
compute symndx, 0 scaleof (1 metadataof value)
compute type, IMAGE_REL_I386_REL32
jump add_relocation
add_relocation:
compute offset, $%
emit 4, 0 scaleof value
check $% > offset
jno done
compute offset, offset - COFF.SECTION_OFFSET
local relocation
compute relocation, COFF.RELOCATION_INDEX * sizeof IMAGE_RELOCATION
asm store offset at COFF.relocations : relocation + IMAGE_RELOCATION.VirtualAddress
asm store symndx at COFF.relocations : relocation + IMAGE_RELOCATION.SymbolTableIndex
asm store type at COFF.relocations : relocation + IMAGE_RELOCATION.Type
compute COFF.RELOCATION_INDEX, COFF.RELOCATION_INDEX + 1
done:
end calminstruction
calminstruction qword? value
compute value, value
check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto COFF.relocatable
jyes dir32
check ~ value relativeto 0 & (value + COFF.IMAGE_BASE) relativeto 1 elementof (value + COFF.IMAGE_BASE) & 1 elementof (1 metadataof (value + COFF.IMAGE_BASE)) relativeto COFF.relocatable
jyes dir32nb
plain:
emit 8, value
exit
local offset, symndx, type
dir32:
compute symndx, 0 scaleof (1 metadataof value)
compute type, IMAGE_REL_I386_DIR32
jump add_relocation
dir32nb:
compute value, value + COFF.IMAGE_BASE
compute symndx, 0 scaleof (1 metadataof value)
compute type, IMAGE_REL_I386_DIR32NB
jump add_relocation
add_relocation:
compute offset, $%
emit 8, 0 scaleof value
check $% > offset
jno done
compute offset, offset - COFF.SECTION_OFFSET
local relocation
compute relocation, COFF.RELOCATION_INDEX * sizeof IMAGE_RELOCATION
asm store offset at COFF.relocations : relocation + IMAGE_RELOCATION.VirtualAddress
asm store symndx at COFF.relocations : relocation + IMAGE_RELOCATION.SymbolTableIndex
asm store type at COFF.relocations : relocation + IMAGE_RELOCATION.Type
compute COFF.RELOCATION_INDEX, COFF.RELOCATION_INDEX + 1
done:
end calminstruction
else if COFF.MACHINE = IMAGE_FILE_MACHINE_AMD64
calminstruction dword? value
compute value, value
check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto COFF.relocatable
jyes addr32
check ~ value relativeto 0 & (value + COFF.IMAGE_BASE) relativeto 1 elementof (value + COFF.IMAGE_BASE) & 1 elementof (1 metadataof (value + COFF.IMAGE_BASE)) relativeto COFF.relocatable
jyes addr32nb
check ~ value relativeto 0 & (value + COFF.SECTION_BASE) relativeto 1 elementof (value + COFF.SECTION_BASE)
jno plain
check 1 elementof (1 metadataof (value + COFF.SECTION_BASE)) relativeto COFF.relocatable
jyes rel32
plain:
emit 4, value
exit
local offset, symndx, type
addr32:
compute symndx, 0 scaleof (1 metadataof value)
compute type, IMAGE_REL_AMD64_ADDR32
jump add_relocation
addr32nb:
compute value, value + COFF.IMAGE_BASE
compute symndx, 0 scaleof (1 metadataof value)
compute type, IMAGE_REL_AMD64_ADDR32NB
jump add_relocation
rel32:
compute value, value + (COFF.SECTION_BASE + $% + 4 - COFF.SECTION_OFFSET)
compute symndx, 0 scaleof (1 metadataof value)
compute type, IMAGE_REL_AMD64_REL32
jump add_relocation
add_relocation:
compute offset, $%
emit 4, 0 scaleof value
check $% > offset
jno done
compute offset, offset - COFF.SECTION_OFFSET
local relocation
compute relocation, COFF.RELOCATION_INDEX * sizeof IMAGE_RELOCATION
asm store offset at COFF.relocations : relocation + IMAGE_RELOCATION.VirtualAddress
asm store symndx at COFF.relocations : relocation + IMAGE_RELOCATION.SymbolTableIndex
asm store type at COFF.relocations : relocation + IMAGE_RELOCATION.Type
compute COFF.RELOCATION_INDEX, COFF.RELOCATION_INDEX + 1
done:
end calminstruction
calminstruction qword? value
compute value, value
check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto COFF.relocatable
jyes addr64
check ~ value relativeto 0 & (value + COFF.IMAGE_BASE) relativeto 1 elementof (value + COFF.IMAGE_BASE) & 1 elementof (1 metadataof (value + COFF.IMAGE_BASE)) relativeto COFF.relocatable
jyes addr64nb
plain:
emit 8, value
exit
local offset, symndx, type
addr64:
compute symndx, 0 scaleof (1 metadataof value)
compute type, IMAGE_REL_AMD64_ADDR64
jump add_relocation
addr64nb:
compute value, value + COFF.IMAGE_BASE
compute symndx, 0 scaleof (1 metadataof value)
compute type, IMAGE_REL_AMD64_ADDR64NB
jump add_relocation
add_relocation:
compute offset, $%
emit 8, 0 scaleof value
check $% > offset
jno done
compute offset, offset - COFF.SECTION_OFFSET
local relocation
compute relocation, COFF.RELOCATION_INDEX * sizeof IMAGE_RELOCATION
asm store offset at COFF.relocations : relocation + IMAGE_RELOCATION.VirtualAddress
asm store symndx at COFF.relocations : relocation + IMAGE_RELOCATION.SymbolTableIndex
asm store type at COFF.relocations : relocation + IMAGE_RELOCATION.Type
compute COFF.RELOCATION_INDEX, COFF.RELOCATION_INDEX + 1
done:
end calminstruction
end if
iterate <dd,dword>, dd,dword, dq,qword
calminstruction dd? definitions&
local value, n
start:
match value=,definitions, definitions, ()
jyes recognize
match value, definitions
arrange definitions,
recognize:
match n =dup? value, value, ()
jyes duplicate
match ?, value
jyes reserve
call dword, value
next:
match , definitions
jno start
take , definitions
take definitions, definitions
jyes next
exit
reserve:
emit dword
jump next
duplicate:
match (value), value
stack:
check n
jno next
take definitions, value
arrange value, definitions
compute n, n - 1
jump stack
end calminstruction
calminstruction (label) dd? definitions&
local cmd
arrange cmd, =label label : =dword
assemble cmd
arrange cmd, =dd definitions
assemble cmd
end calminstruction
end iterate
postpone
purge section?
section
namespace COFF
NUMBER_OF_SECTIONS := SECTION_INDEX
STRING_TABLE_SIZE := STRING_POSITION
NUMBER_OF_SYMBOLS := SYMBOL_INDEX
NUMBER_OF_RELOCATIONS := RELOCATION_INDEX
RELOCATIONS_OFFSET = $%
load byte_sequence : NUMBER_OF_RELOCATIONS * sizeof IMAGE_RELOCATION from relocations:0
db byte_sequence
SYMBOL_TABLE_OFFSET = $%
load byte_sequence : NUMBER_OF_SYMBOLS * sizeof IMAGE_SYMBOL from symbol_table:0
db byte_sequence
load byte_sequence : STRING_TABLE_SIZE from string_table:0
db byte_sequence
end namespace
end postpone

View File

@ -0,0 +1,640 @@
macro struct? name
macro end?.struct?!
end namespace
esc end struc
virtual at 0
name name
sizeof.name = $
end virtual
purge end?.struct?
end macro
esc struc name
label . : sizeof.name
namespace .
end macro
struct Elf32_Shdr
sh_name dd ?
sh_type dd ?
sh_flags dd ?
sh_addr dd ?
sh_offset dd ?
sh_size dd ?
sh_link dd ?
sh_info dd ?
sh_addralign dd ?
sh_entsize dd ?
end struct
struct Elf32_Sym
st_name dd ?
st_value dd ?
st_size dd ?
st_info db ?
st_other db ?
st_shndx dw ?
end struct
struct Elf32_Rel
r_offset dd ?
r_info dd ?
end struct
struct Elf32_Rela
r_offset dd ?
r_info dd ?
r_addend dd ?
end struct
struct Elf32_Phdr
p_type dd ?
p_offset dd ?
p_vaddr dd ?
p_paddr dd ?
p_filesz dd ?
p_memsz dd ?
p_flags dd ?
p_align dd ?
end struct
purge struct?
ELFCLASSNONE = 0
ELFCLASS32 = 1
ELFCLASS64 = 2
ELFDATANONE = 0
ELFDATA2LSB = 1
ELFDATA2MSB = 2
ELFOSABI_NONE = 0
ELFOSABI_HPUX = 1
ELFOSABI_NETBSD = 2
ELFOSABI_GNU = 3
ELFOSABI_LINUX = 3
ELFOSABI_SOLARIS = 6
ELFOSABI_AIX = 7
ELFOSABI_IRIX = 8
ELFOSABI_FREEBSD = 9
ELFOSABI_TRU64 = 10
ELFOSABI_MODESTO = 11
ELFOSABI_OPENBSD = 12
ELFOSABI_OPENVMS = 13
ELFOSABI_NSK = 14
ELFOSABI_AROS = 15
ELFOSABI_FENIXOS = 16
ELFOSABI_CLOUDABI = 17
ELFOSABI_OPENVOS = 18
ET_NONE = 0
ET_REL = 1
ET_EXEC = 2
ET_DYN = 3
ET_CORE = 4
ET_LOPROC = 0xff00
ET_HIPROC = 0xffff
EM_NONE = 0
EM_M32 = 1
EM_SPARC = 2
EM_386 = 3
EM_68K = 4
EM_88K = 5
EM_860 = 7
EM_MIPS = 8
EM_X86_64 = 62
EV_NONE = 0
EV_CURRENT = 1
SHN_UNDEF = 0
SHN_LORESERVE = 0xff00
SHN_LOPROC = 0xff00
SHN_HIPROC = 0xff1f
SHN_ABS = 0xfff1
SHN_COMMON = 0xfff2
SHN_HIRESERVE = 0xffff
SHT_NULL = 0
SHT_PROGBITS = 1
SHT_SYMTAB = 2
SHT_STRTAB = 3
SHT_RELA = 4
SHT_HASH = 5
SHT_DYNAMIC = 6
SHT_NOTE = 7
SHT_NOBITS = 8
SHT_REL = 9
SHT_SHLIB = 10
SHT_DYNSYM = 11
SHT_LOPROC = 0x70000000
SHT_HIPROC = 0x7fffffff
SHT_LOUSER = 0x80000000
SHT_HIUSER = 0xffffffff
SHF_WRITE = 0x1
SHF_ALLOC = 0x2
SHF_EXECINSTR = 0x4
SHF_MASKPROC = 0xf0000000
STT_NOTYPE = 0
STT_OBJECT = 1
STT_FUNC = 2
STT_SECTION = 3
STT_FILE = 4
STT_LOPROC = 13
STT_HIPROC = 15
STB_LOCAL = 0
STB_GLOBAL = 1
STB_WEAK = 2
STB_LOPROC = 13
STB_HIPROC = 15
R_386_NONE = 0
R_386_32 = 1
R_386_PC32 = 2
R_386_GOT32 = 3
R_386_PLT32 = 4
R_386_COPY = 5
R_386_GLOB_DAT = 6
R_386_JMP_SLOT = 7
R_386_RELATIVE = 8
R_386_GOTOFF = 9
R_386_GOTPC = 10
R_X86_64_NONE = 0
R_X86_64_64 = 1
R_X86_64_PC32 = 2
R_X86_64_GOT32 = 3
R_X86_64_PLT32 = 4
R_X86_64_COPY = 5
R_X86_64_GLOB_DAT = 6
R_X86_64_JUMP_SLOT = 7
R_X86_64_RELATIVE = 8
R_X86_64_GOTPCREL = 9
R_X86_64_32 = 10
R_X86_64_32S = 11
R_X86_64_16 = 12
R_X86_64_PC16 = 13
R_X86_64_8 = 14
R_X86_64_PC8 = 15
R_X86_64_DPTMOD64 = 16
R_X86_64_DTPOFF64 = 17
R_X86_64_TPOFF64 = 18
R_X86_64_TLSGD = 19
R_X86_64_TLSLD = 20
R_X86_64_DTPOFF32 = 21
R_X86_64_GOTTPOFF = 22
R_X86_64_TPOFF32 = 23
R_X86_64_PC64 = 24
R_X86_64_GOTOFF64 = 25
R_X86_64_GOTPC32 = 26
ELF::
namespace ELF
if defined Settings.Machine
MACHINE := Settings.Machine
else
MACHINE := EM_386
end if
if defined Settings.ABI
ABI := Settings.ABI
else
ABI := ELFOSABI_NONE
end if
if MACHINE = EM_386
R_32 = R_386_32
R_PC32 = R_386_PC32
R_GOTOFF = R_386_GOTOFF
R_PLT32 = R_386_PLT32
else if MACHINE = EM_X86_64
R_32 = R_X86_64_32
R_PC32 = R_X86_64_PC32
R_PLT32 = R_X86_64_PLT32
end if
Header:
e_ident db 0x7F,'ELF',ELFCLASS32,ELFDATA2LSB,EV_CURRENT,ABI,(16-$) dup 0
e_type dw ET_REL
e_machine dw MACHINE
e_version dd EV_CURRENT
e_entry dd 0
e_phoff dd 0
e_shoff dd SECTION_TABLE_OFFSET
e_flags dd 0
e_ehsize dw Content
e_phentsize dw 0
e_phnum dw 0
e_shentsize dw sizeof Elf32_Shdr
e_shnum dw NUMBER_OF_SECTIONS
e_shstrndx dw STRING_TABLE_SECTION_INDEX
Content:
virtual at 0
section_table:: rb NUMBER_OF_SECTIONS * sizeof Elf32_Shdr
end virtual
virtual at 0
symbol_table:: rb NUMBER_OF_SYMBOLS * sizeof Elf32_Sym
end virtual
virtual at 0
string_table::
_null db 0
_symtab db '.symtab',0
_strtab db '.strtab',0
SECTION_NAME_POSITION = $
rb SECTION_NAME_TABLE_SIZE - $
STRING_POSITION = $
rb STRING_TABLE_SIZE - $
end virtual
virtual at 0
relocations:: rb NUMBER_OF_RELOCATIONS * sizeof Elf32_Rel
end virtual
element relocatable?
macro section_org
local sym
element sym : relocatable * SECTION_INDEX + SECTION_SYMBOL_INDEX
SECTION_BASE = sym
org sym
end macro
RELOCATION_INDEX = 0
SECTION_INDEX = 1
SECTION_SYMBOL_INDEX = SECTION_INDEX
SECTION_RELOCATION_INDEX = RELOCATION_INDEX
SYMBOL_INDEX = NUMBER_OF_SECTION_SYMBOLS
SECTION_OFFSET = $%
SECTION_ALIGN = 4
SECTION_NAME = '.flat'
SECTION_FLAGS = SHF_ALLOC + SHF_WRITE + SHF_EXECINSTR
DEFINED_SECTION = 0
section_org
end namespace
macro section?
namespace ELF
SECTION_SIZE = $% - SECTION_OFFSET
if DEFINED_SECTION | SECTION_SIZE > 0
store SECTION_OFFSET at section_table : Elf32_Shdr.sh_offset + SECTION_INDEX * sizeof Elf32_Shdr
store SECTION_SIZE at section_table : Elf32_Shdr.sh_size + SECTION_INDEX * sizeof Elf32_Shdr
store SECTION_ALIGN at section_table : Elf32_Shdr.sh_addralign + SECTION_INDEX * sizeof Elf32_Shdr
store SECTION_FLAGS at section_table : Elf32_Shdr.sh_flags + SECTION_INDEX * sizeof Elf32_Shdr
if $%% = SECTION_OFFSET
store SHT_NOBITS at section_table : Elf32_Shdr.sh_type + SECTION_INDEX * sizeof Elf32_Shdr
section $
else
store SHT_PROGBITS at section_table : Elf32_Shdr.sh_type + SECTION_INDEX * sizeof Elf32_Shdr
UNINITIALIZED_LENGTH = $% - $%%
section $
db UNINITIALIZED_LENGTH dup 0
end if
store SECTION_INDEX at symbol_table : Elf32_Sym.st_shndx + SECTION_SYMBOL_INDEX * sizeof Elf32_Sym
store STT_SECTION + STB_LOCAL shl 4 at symbol_table : Elf32_Sym.st_info + SECTION_SYMBOL_INDEX * sizeof Elf32_Sym
if RELOCATION_INDEX > SECTION_RELOCATION_INDEX
store RELOCATIONS_OFFSET + SECTION_RELOCATION_INDEX * sizeof Elf32_Rel at section_table : Elf32_Shdr.sh_offset + (SECTION_INDEX+1) * sizeof Elf32_Shdr
store (RELOCATION_INDEX - SECTION_RELOCATION_INDEX) * sizeof Elf32_Rel at section_table : Elf32_Shdr.sh_size + (SECTION_INDEX+1) * sizeof Elf32_Shdr
store SHT_REL at section_table : Elf32_Shdr.sh_type + (SECTION_INDEX+1) * sizeof Elf32_Shdr
store SYMBOL_TABLE_SECTION_INDEX at section_table : Elf32_Shdr.sh_link + (SECTION_INDEX+1) * sizeof Elf32_Shdr
store SECTION_INDEX at section_table : Elf32_Shdr.sh_info + (SECTION_INDEX+1) * sizeof Elf32_Shdr
store sizeof Elf32_Rel at section_table : Elf32_Shdr.sh_entsize + (SECTION_INDEX+1) * sizeof Elf32_Shdr
store 4 at section_table : Elf32_Shdr.sh_addralign + (SECTION_INDEX+1) * sizeof Elf32_Shdr
store SECTION_NAME_POSITION at section_table : Elf32_Shdr.sh_name + (SECTION_INDEX+1) * sizeof Elf32_Shdr
store SECTION_NAME_POSITION + 4 at section_table : Elf32_Shdr.sh_name + SECTION_INDEX * sizeof Elf32_Shdr
store SECTION_NAME_POSITION + 4 at symbol_table : Elf32_Sym.st_name + SECTION_SYMBOL_INDEX * sizeof Elf32_Sym
store '.rel' + SECTION_NAME shl (4*8) : 4 + lengthof (string SECTION_NAME) at string_table:SECTION_NAME_POSITION
SECTION_NAME_POSITION = SECTION_NAME_POSITION + 4 + lengthof (string SECTION_NAME) + 1
SECTION_INDEX = SECTION_INDEX + 2
SECTION_SYMBOL_INDEX = SECTION_SYMBOL_INDEX + 1
else
store SECTION_NAME_POSITION at section_table : Elf32_Shdr.sh_name + SECTION_INDEX * sizeof Elf32_Shdr
store SECTION_NAME_POSITION at symbol_table : Elf32_Sym.st_name + SECTION_SYMBOL_INDEX * sizeof Elf32_Sym
store SECTION_NAME : lengthof (string SECTION_NAME) at string_table:SECTION_NAME_POSITION
SECTION_NAME_POSITION = SECTION_NAME_POSITION + lengthof (string SECTION_NAME) + 1
SECTION_INDEX = SECTION_INDEX + 1
SECTION_SYMBOL_INDEX = SECTION_SYMBOL_INDEX + 1
end if
end if
end namespace
end macro
macro section? declaration*
namespace ELF
section
DEFINED_SECTION = 1
SECTION_FLAGS = SHF_ALLOC
SECTION_OFFSET = $%
SECTION_ALIGN = 4
match name attributes, declaration
SECTION_NAME = name
local seq,list
match flags =align? boundary, attributes
SECTION_ALIGN = boundary
define seq flags
else match =align? boundary, attributes
SECTION_ALIGN = boundary
define seq
else
define seq attributes
end match
while 1
match car cdr, seq
define list car
define seq cdr
else
match any, seq
define list any
end match
break
end match
end while
irpv attribute, list
match =writeable?, attribute
SECTION_FLAGS = SECTION_FLAGS or SHF_WRITE
else match =executable?, attribute
SECTION_FLAGS = SECTION_FLAGS or SHF_EXECINSTR
else
err 'unknown attribute "',`attribute,'"'
end match
end irpv
else
SECTION_NAME = declaration
end match
section_org
SECTION_RELOCATION_INDEX = RELOCATION_INDEX
end namespace
end macro
calminstruction align? boundary,value:?
check ELF.SECTION_ALIGN mod (boundary) = 0
jyes allowed
err 'section not aligned enough'
exit
allowed:
compute boundary, (boundary-1)-($-ELF.SECTION_BASE+boundary-1) mod boundary
arrange value, =db boundary =dup value
assemble value
end calminstruction
macro public? declaration*
namespace ELF
match value =as? str, declaration
SYMBOL_VALUE = value
SYMBOL_SIZE = sizeof value
SYMBOL_NAME = string str
else
SYMBOL_VALUE = declaration
SYMBOL_SIZE = sizeof declaration
SYMBOL_NAME = `declaration
end match
if SYMBOL_VALUE relativeto 1 elementof SYMBOL_VALUE & 1 elementof (1 metadataof SYMBOL_VALUE) relativeto relocatable & 1 scaleof (1 metadataof SYMBOL_VALUE) > 0
SYMBOL_SECTION_INDEX = 1 scaleof (1 metadataof SYMBOL_VALUE)
SYMBOL_VALUE = SYMBOL_VALUE - 1 elementof SYMBOL_VALUE
else
SYMBOL_SECTION_INDEX = SHN_ABS
end if
store STRING_POSITION at symbol_table : Elf32_Sym.st_name + SYMBOL_INDEX * sizeof Elf32_Sym
store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION
STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1
store SYMBOL_VALUE at symbol_table : Elf32_Sym.st_value + SYMBOL_INDEX * sizeof Elf32_Sym
store SYMBOL_SIZE at symbol_table : Elf32_Sym.st_size + SYMBOL_INDEX * sizeof Elf32_Sym
store SYMBOL_SECTION_INDEX at symbol_table : Elf32_Sym.st_shndx + SYMBOL_INDEX * sizeof Elf32_Sym
if SYMBOL_SIZE
store STT_OBJECT + STB_GLOBAL shl 4 at symbol_table : Elf32_Sym.st_info + SYMBOL_INDEX * sizeof Elf32_Sym
else
store STT_FUNC + STB_GLOBAL shl 4 at symbol_table : Elf32_Sym.st_info + SYMBOL_INDEX * sizeof Elf32_Sym
end if
SYMBOL_INDEX = SYMBOL_INDEX + 1
end namespace
end macro
macro extrn? declaration*
namespace ELF
local sym,psym
element sym : relocatable * (-1) + SYMBOL_INDEX
element psym : PLT + SYMBOL_INDEX
match str =as? name:size, declaration
label name:size at sym
label PLT.name at psym
SYMBOL_NAME = string str
SYMBOL_SIZE = size
else match name:size, declaration
label name:size at sym
label PLT.name at psym
SYMBOL_NAME = `name
SYMBOL_SIZE = size
else match str =as? name, declaration
label name at sym
label PLT.name at psym
SYMBOL_NAME = string str
SYMBOL_SIZE = 0
else
label declaration at sym
label PLT.declaration at psym
SYMBOL_NAME = `declaration
SYMBOL_SIZE = 0
end match
store STRING_POSITION at symbol_table : Elf32_Sym.st_name + SYMBOL_INDEX * sizeof Elf32_Sym
store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION
STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1
store SYMBOL_SIZE at symbol_table : Elf32_Sym.st_size + SYMBOL_INDEX * sizeof Elf32_Sym
store STT_NOTYPE + STB_GLOBAL shl 4 at symbol_table : Elf32_Sym.st_info + SYMBOL_INDEX * sizeof Elf32_Sym
SYMBOL_INDEX = SYMBOL_INDEX + 1
end namespace
end macro
element _GLOBAL_OFFSET_TABLE_
RVA? equ -_GLOBAL_OFFSET_TABLE_+
element PLT?
calminstruction calminstruction?.initsym? var*, val&
publish var, val
end calminstruction
calminstruction calminstruction?.asm? line&
local name, i
initsym name, name.0
match name.i, name
compute i, i+1
arrange name, name.i
publish name, line
arrange line, =assemble name
assemble line
end calminstruction
calminstruction dword? value
compute value, value
check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto ELF.relocatable
jyes r_32
check ~ value relativeto 0 & (value + _GLOBAL_OFFSET_TABLE_) relativeto 1 elementof (value + _GLOBAL_OFFSET_TABLE_) & 1 elementof (1 metadataof (value + _GLOBAL_OFFSET_TABLE_)) relativeto ELF.relocatable
jyes r_gotoff
check ~ value relativeto 0 & (value + ELF.SECTION_BASE) relativeto 1 elementof (value + ELF.SECTION_BASE)
jno plain
check 1 elementof (1 metadataof (value + ELF.SECTION_BASE)) relativeto ELF.relocatable
jyes r_pc32
check 1 elementof (1 metadataof (value + ELF.SECTION_BASE)) relativeto PLT
jyes r_plt32
plain:
emit 4, value
exit
local offset, info
r_32:
compute info, ELF.R_32 + (0 scaleof (1 metadataof value)) shl 8
jump add_relocation
r_gotoff:
compute value, value + _GLOBAL_OFFSET_TABLE_
compute info, ELF.R_GOTOFF + (0 scaleof (1 metadataof value)) shl 8
jump add_relocation
r_pc32:
compute value, value + (ELF.SECTION_BASE + $% - ELF.SECTION_OFFSET)
compute info, ELF.R_PC32 + (0 scaleof (1 metadataof value)) shl 8
jump add_relocation
r_plt32:
compute value, value + (ELF.SECTION_BASE + $% - ELF.SECTION_OFFSET)
compute info, ELF.R_PLT32 + (0 scaleof (1 metadataof value)) shl 8
jump add_relocation
add_relocation:
compute offset, $%
emit 4, 0 scaleof value
check $% > offset
jno done
compute offset, offset - ELF.SECTION_OFFSET
local Rel
compute Rel, ELF.RELOCATION_INDEX * sizeof Elf32_Rel
asm store offset at ELF.relocations : Rel + Elf32_Rel.r_offset
asm store info at ELF.relocations : Rel + Elf32_Rel.r_info
compute ELF.RELOCATION_INDEX, ELF.RELOCATION_INDEX + 1
done:
end calminstruction
calminstruction dd? definitions&
local value, n
start:
match value=,definitions, definitions, ()
jyes recognize
match value, definitions
arrange definitions,
recognize:
match n =dup? value, value, ()
jyes duplicate
match ?, value
jyes reserve
call dword, value
next:
match , definitions
jno start
take , definitions
take definitions, definitions
jyes next
exit
reserve:
emit dword
jump next
duplicate:
match (value), value
stack:
check n
jno next
take definitions, value
arrange value, definitions
compute n, n - 1
jump stack
end calminstruction
calminstruction (label) dd? definitions&
local cmd
arrange cmd, =label label : =dword
assemble cmd
arrange cmd, =dd definitions
assemble cmd
end calminstruction
postpone
purge section?
section
namespace ELF
SECTION_NAME_TABLE_SIZE := SECTION_NAME_POSITION
STRING_TABLE_SIZE := STRING_POSITION
NUMBER_OF_SECTION_SYMBOLS := SECTION_SYMBOL_INDEX
NUMBER_OF_SYMBOLS := SYMBOL_INDEX
SYMBOL_TABLE_SIZE := NUMBER_OF_SYMBOLS * sizeof Elf32_Sym
NUMBER_OF_RELOCATIONS := RELOCATION_INDEX
rb (-$%) and 11b
RELOCATIONS_OFFSET = $%
load byte_sequence : NUMBER_OF_RELOCATIONS * sizeof Elf32_Rel from relocations:0
db byte_sequence
store _symtab at section_table : Elf32_Shdr.sh_name + SECTION_INDEX * sizeof Elf32_Shdr
store $% at section_table : Elf32_Shdr.sh_offset + SECTION_INDEX * sizeof Elf32_Shdr
store SYMBOL_TABLE_SIZE at section_table : Elf32_Shdr.sh_size + SECTION_INDEX * sizeof Elf32_Shdr
store sizeof Elf32_Sym at section_table : Elf32_Shdr.sh_entsize + SECTION_INDEX * sizeof Elf32_Shdr
store 4 at section_table : Elf32_Shdr.sh_addralign + SECTION_INDEX * sizeof Elf32_Shdr
store SHT_SYMTAB at section_table : Elf32_Shdr.sh_type + SECTION_INDEX * sizeof Elf32_Shdr
store STRING_TABLE_SECTION_INDEX at section_table : Elf32_Shdr.sh_link + SECTION_INDEX * sizeof Elf32_Shdr
store NUMBER_OF_SECTION_SYMBOLS at section_table : Elf32_Shdr.sh_info + SECTION_INDEX * sizeof Elf32_Shdr
SYMBOL_TABLE_SECTION_INDEX := SECTION_INDEX
load byte_sequence : SYMBOL_TABLE_SIZE from symbol_table:0
db byte_sequence
SECTION_INDEX = SECTION_INDEX + 1
store _strtab at section_table : Elf32_Shdr.sh_name + SECTION_INDEX * sizeof Elf32_Shdr
store $% at section_table : Elf32_Shdr.sh_offset + SECTION_INDEX * sizeof Elf32_Shdr
store STRING_TABLE_SIZE at section_table : Elf32_Shdr.sh_size + SECTION_INDEX * sizeof Elf32_Shdr
store 1 at section_table : Elf32_Shdr.sh_addralign + SECTION_INDEX * sizeof Elf32_Shdr
store SHT_STRTAB at section_table : Elf32_Shdr.sh_type + SECTION_INDEX * sizeof Elf32_Shdr
STRING_TABLE_SECTION_INDEX := SECTION_INDEX
load byte_sequence : STRING_TABLE_SIZE from string_table:0
db byte_sequence
SECTION_INDEX = SECTION_INDEX + 1
assert SECTION_INDEX <= SHN_LORESERVE
NUMBER_OF_SECTIONS := SECTION_INDEX
rb (-$%) and 11b
SECTION_TABLE_OFFSET := $%
load byte_sequence : NUMBER_OF_SECTIONS * sizeof Elf32_Shdr from section_table:0
db byte_sequence
end namespace
end postpone

View File

@ -0,0 +1,652 @@
macro struct? name
macro end?.struct?!
end namespace
esc end struc
virtual at 0
name name
sizeof.name = $
end virtual
purge end?.struct?
end macro
esc struc name
label . : sizeof.name
namespace .
end macro
struct Elf64_Shdr
sh_name dd ?
sh_type dd ?
sh_flags dq ?
sh_addr dq ?
sh_offset dq ?
sh_size dq ?
sh_link dd ?
sh_info dd ?
sh_addralign dq ?
sh_entsize dq ?
end struct
struct Elf64_Sym
st_name dd ?
st_info db ?
st_other db ?
st_shndx dw ?
st_value dq ?
st_size dq ?
end struct
struct Elf64_Rel
r_offset dq ?
r_info dq ?
end struct
struct Elf64_Rela
r_offset dq ?
r_info dq ?
r_addend dq ?
end struct
struct Elf64_Phdr
p_type dd ?
p_flags dd ?
p_offset dq ?
p_vaddr dq ?
p_paddr dq ?
p_filesz dq ?
p_memsz dq ?
p_align dq ?
end struct
purge struct?
ELFCLASSNONE = 0
ELFCLASS32 = 1
ELFCLASS64 = 2
ELFDATANONE = 0
ELFDATA2LSB = 1
ELFDATA2MSB = 2
ELFOSABI_NONE = 0
ELFOSABI_HPUX = 1
ELFOSABI_NETBSD = 2
ELFOSABI_GNU = 3
ELFOSABI_LINUX = 3
ELFOSABI_SOLARIS = 6
ELFOSABI_AIX = 7
ELFOSABI_IRIX = 8
ELFOSABI_FREEBSD = 9
ELFOSABI_TRU64 = 10
ELFOSABI_MODESTO = 11
ELFOSABI_OPENBSD = 12
ELFOSABI_OPENVMS = 13
ELFOSABI_NSK = 14
ELFOSABI_AROS = 15
ELFOSABI_FENIXOS = 16
ELFOSABI_CLOUDABI = 17
ELFOSABI_OPENVOS = 18
ET_NONE = 0
ET_REL = 1
ET_EXEC = 2
ET_DYN = 3
ET_CORE = 4
ET_LOPROC = 0xff00
ET_HIPROC = 0xffff
EM_NONE = 0
EM_IA_64 = 50
EM_X86_64 = 62
EV_NONE = 0
EV_CURRENT = 1
SHN_UNDEF = 0
SHN_LORESERVE = 0xff00
SHN_LOPROC = 0xff00
SHN_HIPROC = 0xff1f
SHN_ABS = 0xfff1
SHN_COMMON = 0xfff2
SHN_HIRESERVE = 0xffff
SHT_NULL = 0
SHT_PROGBITS = 1
SHT_SYMTAB = 2
SHT_STRTAB = 3
SHT_RELA = 4
SHT_HASH = 5
SHT_DYNAMIC = 6
SHT_NOTE = 7
SHT_NOBITS = 8
SHT_REL = 9
SHT_SHLIB = 10
SHT_DYNSYM = 11
SHT_LOPROC = 0x70000000
SHT_HIPROC = 0x7fffffff
SHT_LOUSER = 0x80000000
SHT_HIUSER = 0xffffffff
SHF_WRITE = 0x1
SHF_ALLOC = 0x2
SHF_EXECINSTR = 0x4
SHF_MASKPROC = 0xf0000000
STT_NOTYPE = 0
STT_OBJECT = 1
STT_FUNC = 2
STT_SECTION = 3
STT_FILE = 4
STT_LOPROC = 13
STT_HIPROC = 15
STB_LOCAL = 0
STB_GLOBAL = 1
STB_WEAK = 2
STB_LOPROC = 13
STB_HIPROC = 15
R_X86_64_NONE = 0
R_X86_64_64 = 1
R_X86_64_PC32 = 2
R_X86_64_GOT32 = 3
R_X86_64_PLT32 = 4
R_X86_64_COPY = 5
R_X86_64_GLOB_DAT = 6
R_X86_64_JUMP_SLOT = 7
R_X86_64_RELATIVE = 8
R_X86_64_GOTPCREL = 9
R_X86_64_32 = 10
R_X86_64_32S = 11
R_X86_64_16 = 12
R_X86_64_PC16 = 13
R_X86_64_8 = 14
R_X86_64_PC8 = 15
R_X86_64_DPTMOD64 = 16
R_X86_64_DTPOFF64 = 17
R_X86_64_TPOFF64 = 18
R_X86_64_TLSGD = 19
R_X86_64_TLSLD = 20
R_X86_64_DTPOFF32 = 21
R_X86_64_GOTTPOFF = 22
R_X86_64_TPOFF32 = 23
R_X86_64_PC64 = 24
R_X86_64_GOTOFF64 = 25
R_X86_64_GOTPC32 = 26
ELF::
namespace ELF
if defined Settings.Machine
MACHINE := Settings.Machine
else
MACHINE := EM_X86_64
end if
if defined Settings.ABI
ABI := Settings.ABI
else
ABI := ELFOSABI_NONE
end if
if MACHINE = EM_X86_64
R_64 = R_X86_64_64
R_32 = R_X86_64_32S
R_PC32 = R_X86_64_PC32
R_PLT32 = R_X86_64_PLT32
end if
Header:
e_ident db 0x7F,'ELF',ELFCLASS64,ELFDATA2LSB,EV_CURRENT,ABI,(16-$) dup 0
e_type dw ET_REL
e_machine dw MACHINE
e_version dd EV_CURRENT
e_entry dq 0
e_phoff dq 0
e_shoff dq SECTION_TABLE_OFFSET
e_flags dd 0
e_ehsize dw Content
e_phentsize dw 0
e_phnum dw 0
e_shentsize dw sizeof Elf64_Shdr
e_shnum dw NUMBER_OF_SECTIONS
e_shstrndx dw STRING_TABLE_SECTION_INDEX
Content:
virtual at 0
section_table:: rb NUMBER_OF_SECTIONS * sizeof Elf64_Shdr
end virtual
virtual at 0
symbol_table:: rb NUMBER_OF_SYMBOLS * sizeof Elf64_Sym
end virtual
virtual at 0
string_table::
_null db 0
_symtab db '.symtab',0
_strtab db '.strtab',0
SECTION_NAME_POSITION = $
rb SECTION_NAME_TABLE_SIZE - $
STRING_POSITION = $
rb STRING_TABLE_SIZE - $
end virtual
virtual at 0
relocations:: rb NUMBER_OF_RELOCATIONS * sizeof Elf64_Rela
end virtual
element relocatable?
macro section_org
local sym
element sym : relocatable * SECTION_INDEX + SECTION_SYMBOL_INDEX
SECTION_BASE = sym
org sym
end macro
RELOCATION_INDEX = 0
SECTION_INDEX = 1
SECTION_SYMBOL_INDEX = SECTION_INDEX
SECTION_RELOCATION_INDEX = RELOCATION_INDEX
SYMBOL_INDEX = NUMBER_OF_SECTION_SYMBOLS
SECTION_OFFSET = $%
SECTION_ALIGN = 8
SECTION_NAME = '.flat'
SECTION_FLAGS = SHF_ALLOC + SHF_WRITE + SHF_EXECINSTR
DEFINED_SECTION = 0
section_org
end namespace
macro section?
namespace ELF
SECTION_SIZE = $% - SECTION_OFFSET
if DEFINED_SECTION | SECTION_SIZE > 0
store SECTION_OFFSET at section_table : Elf64_Shdr.sh_offset + SECTION_INDEX * sizeof Elf64_Shdr
store SECTION_SIZE at section_table : Elf64_Shdr.sh_size + SECTION_INDEX * sizeof Elf64_Shdr
store SECTION_ALIGN at section_table : Elf64_Shdr.sh_addralign + SECTION_INDEX * sizeof Elf64_Shdr
store SECTION_FLAGS at section_table : Elf64_Shdr.sh_flags + SECTION_INDEX * sizeof Elf64_Shdr
if $%% = SECTION_OFFSET
store SHT_NOBITS at section_table : Elf64_Shdr.sh_type + SECTION_INDEX * sizeof Elf64_Shdr
section $
else
store SHT_PROGBITS at section_table : Elf64_Shdr.sh_type + SECTION_INDEX * sizeof Elf64_Shdr
UNINITIALIZED_LENGTH = $% - $%%
section $
db UNINITIALIZED_LENGTH dup 0
end if
store SECTION_INDEX at symbol_table : Elf64_Sym.st_shndx + SECTION_SYMBOL_INDEX * sizeof Elf64_Sym
store STT_SECTION + STB_LOCAL shl 4 at symbol_table : Elf64_Sym.st_info + SECTION_SYMBOL_INDEX * sizeof Elf64_Sym
if RELOCATION_INDEX > SECTION_RELOCATION_INDEX
store RELOCATIONS_OFFSET + SECTION_RELOCATION_INDEX * sizeof Elf64_Rela at section_table : Elf64_Shdr.sh_offset + (SECTION_INDEX+1) * sizeof Elf64_Shdr
store (RELOCATION_INDEX - SECTION_RELOCATION_INDEX) * sizeof Elf64_Rela at section_table : Elf64_Shdr.sh_size + (SECTION_INDEX+1) * sizeof Elf64_Shdr
store SHT_RELA at section_table : Elf64_Shdr.sh_type + (SECTION_INDEX+1) * sizeof Elf64_Shdr
store SYMBOL_TABLE_SECTION_INDEX at section_table : Elf64_Shdr.sh_link + (SECTION_INDEX+1) * sizeof Elf64_Shdr
store SECTION_INDEX at section_table : Elf64_Shdr.sh_info + (SECTION_INDEX+1) * sizeof Elf64_Shdr
store sizeof Elf64_Rela at section_table : Elf64_Shdr.sh_entsize + (SECTION_INDEX+1) * sizeof Elf64_Shdr
store 8 at section_table : Elf64_Shdr.sh_addralign + (SECTION_INDEX+1) * sizeof Elf64_Shdr
store SECTION_NAME_POSITION at section_table : Elf64_Shdr.sh_name + (SECTION_INDEX+1) * sizeof Elf64_Shdr
store SECTION_NAME_POSITION + 5 at section_table : Elf64_Shdr.sh_name + SECTION_INDEX * sizeof Elf64_Shdr
store SECTION_NAME_POSITION + 5 at symbol_table : Elf64_Sym.st_name + SECTION_SYMBOL_INDEX * sizeof Elf64_Sym
store '.rela' + SECTION_NAME shl (5*8) : 5 + lengthof (string SECTION_NAME) at string_table:SECTION_NAME_POSITION
SECTION_NAME_POSITION = SECTION_NAME_POSITION + 5 + lengthof (string SECTION_NAME) + 1
SECTION_INDEX = SECTION_INDEX + 2
SECTION_SYMBOL_INDEX = SECTION_SYMBOL_INDEX + 1
else
store SECTION_NAME_POSITION at section_table : Elf64_Shdr.sh_name + SECTION_INDEX * sizeof Elf64_Shdr
store SECTION_NAME_POSITION at symbol_table : Elf64_Sym.st_name + SECTION_SYMBOL_INDEX * sizeof Elf64_Sym
store SECTION_NAME : lengthof (string SECTION_NAME) at string_table:SECTION_NAME_POSITION
SECTION_NAME_POSITION = SECTION_NAME_POSITION + lengthof (string SECTION_NAME) + 1
SECTION_INDEX = SECTION_INDEX + 1
SECTION_SYMBOL_INDEX = SECTION_SYMBOL_INDEX + 1
end if
end if
end namespace
end macro
macro section? declaration*
namespace ELF
section
DEFINED_SECTION = 1
SECTION_FLAGS = SHF_ALLOC
SECTION_OFFSET = $%
SECTION_ALIGN = 8
match name attributes, declaration
SECTION_NAME = name
local seq,list
match flags =align? boundary, attributes
SECTION_ALIGN = boundary
define seq flags
else match =align? boundary, attributes
SECTION_ALIGN = boundary
define seq
else
define seq attributes
end match
while 1
match car cdr, seq
define list car
define seq cdr
else
match any, seq
define list any
end match
break
end match
end while
irpv attribute, list
match =writeable?, attribute
SECTION_FLAGS = SECTION_FLAGS or SHF_WRITE
else match =executable?, attribute
SECTION_FLAGS = SECTION_FLAGS or SHF_EXECINSTR
else
err 'unknown attribute "',`attribute,'"'
end match
end irpv
else
SECTION_NAME = declaration
end match
section_org
SECTION_RELOCATION_INDEX = RELOCATION_INDEX
end namespace
end macro
calminstruction align? boundary,value:?
check ELF.SECTION_ALIGN mod (boundary) = 0
jyes allowed
err 'section not aligned enough'
exit
allowed:
compute boundary, (boundary-1)-($-ELF.SECTION_BASE+boundary-1) mod boundary
arrange value, =db boundary =dup value
assemble value
end calminstruction
macro public? declaration*
namespace ELF
match value =as? str, declaration
SYMBOL_VALUE = value
SYMBOL_SIZE = sizeof value
SYMBOL_NAME = string str
else
SYMBOL_VALUE = declaration
SYMBOL_SIZE = sizeof declaration
SYMBOL_NAME = `declaration
end match
if SYMBOL_VALUE relativeto 1 elementof SYMBOL_VALUE & 1 elementof (1 metadataof SYMBOL_VALUE) relativeto relocatable & 1 scaleof (1 metadataof SYMBOL_VALUE) > 0
SYMBOL_SECTION_INDEX = 1 scaleof (1 metadataof SYMBOL_VALUE)
SYMBOL_VALUE = SYMBOL_VALUE - 1 elementof SYMBOL_VALUE
else
SYMBOL_SECTION_INDEX = SHN_ABS
end if
store STRING_POSITION at symbol_table : Elf64_Sym.st_name + SYMBOL_INDEX * sizeof Elf64_Sym
store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION
STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1
store SYMBOL_VALUE at symbol_table : Elf64_Sym.st_value + SYMBOL_INDEX * sizeof Elf64_Sym
store SYMBOL_SIZE at symbol_table : Elf64_Sym.st_size + SYMBOL_INDEX * sizeof Elf64_Sym
store SYMBOL_SECTION_INDEX at symbol_table : Elf64_Sym.st_shndx + SYMBOL_INDEX * sizeof Elf64_Sym
if SYMBOL_SIZE
store STT_OBJECT + STB_GLOBAL shl 4 at symbol_table : Elf64_Sym.st_info + SYMBOL_INDEX * sizeof Elf64_Sym
else
store STT_FUNC + STB_GLOBAL shl 4 at symbol_table : Elf64_Sym.st_info + SYMBOL_INDEX * sizeof Elf64_Sym
end if
SYMBOL_INDEX = SYMBOL_INDEX + 1
end namespace
end macro
macro extrn? declaration*
namespace ELF
local sym,psym
element sym : relocatable * (-1) + SYMBOL_INDEX
element psym : PLT + SYMBOL_INDEX
match str =as? name:size, declaration
label name:size at sym
label PLT.name at psym
SYMBOL_NAME = string str
SYMBOL_SIZE = size
else match name:size, declaration
label name:size at sym
label PLT.name at psym
SYMBOL_NAME = `name
SYMBOL_SIZE = size
else match str =as? name, declaration
label name at sym
label PLT.name at psym
SYMBOL_NAME = string str
SYMBOL_SIZE = 0
else
label declaration at sym
label PLT.declaration at psym
SYMBOL_NAME = `declaration
SYMBOL_SIZE = 0
end match
store STRING_POSITION at symbol_table : Elf64_Sym.st_name + SYMBOL_INDEX * sizeof Elf64_Sym
store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION
STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1
store SYMBOL_SIZE at symbol_table : Elf64_Sym.st_size + SYMBOL_INDEX * sizeof Elf64_Sym
store STT_NOTYPE + STB_GLOBAL shl 4 at symbol_table : Elf64_Sym.st_info + SYMBOL_INDEX * sizeof Elf64_Sym
SYMBOL_INDEX = SYMBOL_INDEX + 1
end namespace
end macro
element PLT?
calminstruction calminstruction?.initsym? var*, val&
publish var, val
end calminstruction
calminstruction calminstruction?.asm? line&
local name, i
initsym name, name.0
match name.i, name
compute i, i+1
arrange name, name.i
publish name, line
arrange line, =assemble name
assemble line
end calminstruction
calminstruction dword? value
compute value, value
check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto ELF.relocatable
jyes r_32
check ~ value relativeto 0 & (value + ELF.SECTION_BASE) relativeto 1 elementof (value + ELF.SECTION_BASE)
jno plain
check 1 elementof (1 metadataof (value + ELF.SECTION_BASE)) relativeto ELF.relocatable
jyes r_pc32
check 1 elementof (1 metadataof (value + ELF.SECTION_BASE)) relativeto PLT
jyes r_plt32
plain:
emit 4, value
exit
local offset, addend, info
r_32:
compute offset, $%
emit 4
check $% > offset
jno done
compute offset, offset - ELF.SECTION_OFFSET
compute addend, 0 scaleof value
compute info, ELF.R_32 + (0 scaleof (1 metadataof value)) shl 32
jump add_relocation
r_pc32:
compute offset, $%
emit 4
check $% > offset
jno done
compute offset, offset - ELF.SECTION_OFFSET
compute addend, 0 scaleof (value + ELF.SECTION_BASE + offset)
compute info, ELF.R_PC32 + (0 scaleof (1 metadataof value)) shl 32
jump add_relocation
r_plt32:
compute offset, $%
emit 4
check $% > offset
jno done
compute offset, offset - ELF.SECTION_OFFSET
compute addend, 0 scaleof (value + ELF.SECTION_BASE + offset)
compute info, ELF.R_PLT32 + (0 scaleof (1 metadataof value)) shl 32
jump add_relocation
add_relocation:
local Rela
compute Rela, ELF.RELOCATION_INDEX * sizeof Elf64_Rela
asm store offset at ELF.relocations : Rela + Elf64_Rela.r_offset
asm store addend at ELF.relocations : Rela + Elf64_Rela.r_addend
asm store info at ELF.relocations : Rela + Elf64_Rela.r_info
compute ELF.RELOCATION_INDEX, ELF.RELOCATION_INDEX + 1
done:
end calminstruction
calminstruction qword? value
compute value, value
check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto ELF.relocatable
jyes r_64
plain:
emit 8, value
exit
local offset, addend, info
r_64:
compute offset, $%
emit 8
check $% > offset
jno done
compute offset, offset - ELF.SECTION_OFFSET
compute addend, 0 scaleof value
compute info, ELF.R_64 + (0 scaleof (1 metadataof value)) shl 32
add_relocation:
local Rela
compute Rela, ELF.RELOCATION_INDEX * sizeof Elf64_Rela
asm store offset at ELF.relocations : Rela + Elf64_Rela.r_offset
asm store addend at ELF.relocations : Rela + Elf64_Rela.r_addend
asm store info at ELF.relocations : Rela + Elf64_Rela.r_info
compute ELF.RELOCATION_INDEX, ELF.RELOCATION_INDEX + 1
done:
end calminstruction
iterate <dd,dword>, dd,dword, dq,qword
calminstruction dd? definitions&
local value, n
start:
match value=,definitions, definitions, ()
jyes recognize
match value, definitions
arrange definitions,
recognize:
match n =dup? value, value, ()
jyes duplicate
match ?, value
jyes reserve
call dword, value
next:
match , definitions
jno start
take , definitions
take definitions, definitions
jyes next
exit
reserve:
emit dword
jump next
duplicate:
match (value), value
stack:
check n
jno next
take definitions, value
arrange value, definitions
compute n, n - 1
jump stack
end calminstruction
calminstruction (label) dd? definitions&
local cmd
arrange cmd, =label label : =dword
assemble cmd
arrange cmd, =dd definitions
assemble cmd
end calminstruction
end iterate
postpone
purge section?
section
namespace ELF
SECTION_NAME_TABLE_SIZE := SECTION_NAME_POSITION
STRING_TABLE_SIZE := STRING_POSITION
NUMBER_OF_SECTION_SYMBOLS := SECTION_SYMBOL_INDEX
NUMBER_OF_SYMBOLS := SYMBOL_INDEX
SYMBOL_TABLE_SIZE := NUMBER_OF_SYMBOLS * sizeof Elf64_Sym
NUMBER_OF_RELOCATIONS := RELOCATION_INDEX
rb (-$%) and 111b
RELOCATIONS_OFFSET = $%
load byte_sequence : NUMBER_OF_RELOCATIONS * sizeof Elf64_Rela from relocations:0
db byte_sequence
store _symtab at section_table : Elf64_Shdr.sh_name + SECTION_INDEX * sizeof Elf64_Shdr
store $% at section_table : Elf64_Shdr.sh_offset + SECTION_INDEX * sizeof Elf64_Shdr
store SYMBOL_TABLE_SIZE at section_table : Elf64_Shdr.sh_size + SECTION_INDEX * sizeof Elf64_Shdr
store sizeof Elf64_Sym at section_table : Elf64_Shdr.sh_entsize + SECTION_INDEX * sizeof Elf64_Shdr
store 8 at section_table : Elf64_Shdr.sh_addralign + SECTION_INDEX * sizeof Elf64_Shdr
store SHT_SYMTAB at section_table : Elf64_Shdr.sh_type + SECTION_INDEX * sizeof Elf64_Shdr
store STRING_TABLE_SECTION_INDEX at section_table : Elf64_Shdr.sh_link + SECTION_INDEX * sizeof Elf64_Shdr
store NUMBER_OF_SECTION_SYMBOLS at section_table : Elf64_Shdr.sh_info + SECTION_INDEX * sizeof Elf64_Shdr
SYMBOL_TABLE_SECTION_INDEX := SECTION_INDEX
load byte_sequence : SYMBOL_TABLE_SIZE from symbol_table:0
db byte_sequence
SECTION_INDEX = SECTION_INDEX + 1
store _strtab at section_table : Elf64_Shdr.sh_name + SECTION_INDEX * sizeof Elf64_Shdr
store $% at section_table : Elf64_Shdr.sh_offset + SECTION_INDEX * sizeof Elf64_Shdr
store STRING_TABLE_SIZE at section_table : Elf64_Shdr.sh_size + SECTION_INDEX * sizeof Elf64_Shdr
store 1 at section_table : Elf64_Shdr.sh_addralign + SECTION_INDEX * sizeof Elf64_Shdr
store SHT_STRTAB at section_table : Elf64_Shdr.sh_type + SECTION_INDEX * sizeof Elf64_Shdr
STRING_TABLE_SECTION_INDEX := SECTION_INDEX
load byte_sequence : STRING_TABLE_SIZE from string_table:0
db byte_sequence
SECTION_INDEX = SECTION_INDEX + 1
assert SECTION_INDEX <= SHN_LORESERVE
NUMBER_OF_SECTIONS := SECTION_INDEX
rb (-$%) and 111b
SECTION_TABLE_OFFSET := $%
load byte_sequence : NUMBER_OF_SECTIONS * sizeof Elf64_Shdr from section_table:0
db byte_sequence
end namespace
end postpone

View File

@ -0,0 +1,326 @@
ELFCLASSNONE = 0
ELFCLASS32 = 1
ELFCLASS64 = 2
ELFDATANONE = 0
ELFDATA2LSB = 1
ELFDATA2MSB = 2
ELFOSABI_NONE = 0
ELFOSABI_HPUX = 1
ELFOSABI_NETBSD = 2
ELFOSABI_GNU = 3
ELFOSABI_LINUX = 3
ELFOSABI_SOLARIS = 6
ELFOSABI_AIX = 7
ELFOSABI_IRIX = 8
ELFOSABI_FREEBSD = 9
ELFOSABI_TRU64 = 10
ELFOSABI_MODESTO = 11
ELFOSABI_OPENBSD = 12
ELFOSABI_OPENVMS = 13
ELFOSABI_NSK = 14
ELFOSABI_AROS = 15
ELFOSABI_FENIXOS = 16
ELFOSABI_CLOUDABI = 17
ELFOSABI_OPENVOS = 18
ET_NONE = 0
ET_REL = 1
ET_EXEC = 2
ET_DYN = 3
ET_CORE = 4
ET_LOPROC = 0xff00
ET_HIPROC = 0xffff
EM_NONE = 0
EM_M32 = 1
EM_SPARC = 2
EM_386 = 3
EM_68K = 4
EM_88K = 5
EM_860 = 7
EM_MIPS = 8
EM_X86_64 = 62
EV_NONE = 0
EV_CURRENT = 1
PT_NULL = 0
PT_LOAD = 1
PT_DYNAMIC = 2
PT_INTERP = 3
PT_NOTE = 4
PT_SHLIB = 5
PT_PHDR = 6
PT_GNU_EH_FRAME = 0x6474e550
PT_GNU_STACK = 0x6474e551
PT_GNU_RELRO = 0x6474e552
PT_LOPROC = 0x70000000
PT_HIPROC = 0x7fffffff
PF_X = 1
PF_W = 2
PF_R = 4
PF_MASKOS = 0x0ff00000
PF_MASKPROC = 0xf0000000
calminstruction align? boundary,value:?
compute boundary, (boundary-1)-($-ELF.DYNAMIC+boundary-1) mod boundary
arrange value, =db boundary =dup value
assemble value
end calminstruction
ELF::
namespace ELF
if defined Settings.Class
CLASS := Settings.Class
else
CLASS := ELFCLASS32
end if
if defined Settings.Type
TYPE := Settings.Type
else
TYPE := ET_EXEC
end if
if defined Settings.Machine
MACHINE := Settings.Machine
else
MACHINE := EM_386
end if
if defined Settings.ABI
ABI := Settings.ABI
else
ABI := ELFOSABI_NONE
end if
if TYPE = ET_DYN
element DYNAMIC
else
DYNAMIC := 0
end if
if defined Settings.BaseAddress
BASE_ADDRESS := DYNAMIC + Settings.BaseAddress
else
BASE_ADDRESS := DYNAMIC + 8048000h
end if
if defined Settings.LoadHeaders
LOAD_HEADERS := Settings.LoadHeaders
else
LOAD_HEADERS := 1
end if
Header:
e_ident db 0x7F,'ELF',CLASS,ELFDATA2LSB,EV_CURRENT,ABI,(16-$) dup 0
e_type dw TYPE
e_machine dw MACHINE
e_version dd EV_CURRENT
if CLASS <> ELFCLASS64
e_entry dd start - DYNAMIC
e_phoff dd ProgramHeader
e_shoff dd 0
e_flags dd 0
e_ehsize dw ProgramHeader
e_phentsize dw SEGMENT_HEADER_LENGTH
e_phnum dw NUMBER_OF_SEGMENTS
e_shentsize dw 28h
e_shnum dw 0
e_shstrndx dw 0
else
e_entry dq start - DYNAMIC
e_phoff dq ProgramHeader
e_shoff dq 0
e_flags dd 0
e_ehsize dw ProgramHeader
e_phentsize dw SEGMENT_HEADER_LENGTH
e_phnum dw NUMBER_OF_SEGMENTS
e_shentsize dw 40h
e_shnum dw 0
e_shstrndx dw 0
end if
ProgramHeader:
if CLASS <> ELFCLASS64
p_type dd PT_LOAD
p_offset dd 0
p_vaddr dd BASE_ADDRESS - DYNAMIC
p_paddr dd BASE_ADDRESS - DYNAMIC
p_filesz dd 0
p_memsz dd 0
p_flags dd PF_R+PF_W+PF_X
p_align dd 1000h
else
p_type dd PT_LOAD
p_flags dd PF_R+PF_W+PF_X
p_offset dq 0
p_vaddr dq BASE_ADDRESS - DYNAMIC
p_paddr dq BASE_ADDRESS - DYNAMIC
p_filesz dq 0
p_memsz dq 0
p_align dq 1000h
end if
SEGMENT_HEADER_LENGTH = $ - ProgramHeader
db (NUMBER_OF_SEGMENTS-1)*SEGMENT_HEADER_LENGTH dup 0
HEADERS_OFFSET = 0
HEADERS_BASE = BASE_ADDRESS
OVERLAY_HEADERS = LOAD_HEADERS
SEGMENT_INDEX = 0
DEFINED_SEGMENT = 0
SEGMENT_TYPE = PT_LOAD
FILE_OFFSET = $%
SEGMENT_BASE = BASE_ADDRESS + FILE_OFFSET and 0FFFh
org SEGMENT_BASE
start:
end namespace
RVA? equ -ELF.BASE_ADDRESS +
macro entry? address*
namespace ELF
store address-DYNAMIC at ELF:e_entry
end namespace
end macro
macro segment?
namespace ELF
DEFINED_SEGMENT_SIZE = $ - SEGMENT_BASE
if (DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0) & SEGMENT_TYPE = PT_LOAD & OVERLAY_HEADERS
FILE_OFFSET = HEADERS_OFFSET
SEGMENT_BASE = HEADERS_BASE
OVERLAY_HEADERS = 0
end if
store SEGMENT_BASE-DYNAMIC at ELF:p_vaddr+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH
store SEGMENT_BASE-DYNAMIC at ELF:p_paddr+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH
store FILE_OFFSET at ELF:p_offset+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH
if SEGMENT_TYPE = PT_LOAD
RAW_DATA_SIZE = $%% - FILE_OFFSET
SEGMENT_SIZE = $ - SEGMENT_BASE
store RAW_DATA_SIZE at ELF:p_filesz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH
store SEGMENT_SIZE at ELF:p_memsz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH
if DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0
FILE_OFFSET = $%%
align 1000h
SEGMENT_BASE = $ + FILE_OFFSET and 0FFFh
end if
section SEGMENT_BASE
else
if OVERLAY_HEADERS = 0 & ( LOAD_HEADERS | SEGMENT_TYPE = PT_GNU_RELRO ) & ~ SEGMENT_TYPE = PT_GNU_STACK & ~ SEGMENT_TYPE = PT_NOTE
OVERLAY_HEADERS = 1
HEADERS_OFFSET = FILE_OFFSET
HEADERS_BASE = SEGMENT_BASE
end if
FILE_OFFSET = $%
SEGMENT_SIZE = $ - SEGMENT_BASE
store SEGMENT_SIZE at ELF:p_filesz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH
store SEGMENT_SIZE at ELF:p_memsz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH
if OVERLAY_HEADERS = 0
SEGMENT_BASE = DYNAMIC + (SEGMENT_BASE-DYNAMIC) and not 0FFFh + FILE_OFFSET and 0FFFh
else
SEGMENT_BASE = $
end if
if $% > $%%
store 0:byte at $-1
end if
org SEGMENT_BASE
end if
if DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0
SEGMENT_INDEX = SEGMENT_INDEX + 1
end if
end namespace
end macro
macro segment? attributes*
namespace ELF
segment
SEGMENT_TYPE = PT_LOAD
SEGMENT_FLAGS = 0
local seq,list
define seq attributes
while 1
match car cdr, seq
define list car
define seq cdr
else
match any, seq
define list any
end match
break
end match
end while
irpv attribute, list
match =readable?, attribute
SEGMENT_FLAGS = SEGMENT_FLAGS or PF_R
else match =writeable?, attribute
SEGMENT_FLAGS = SEGMENT_FLAGS or PF_W
else match =executable?, attribute
SEGMENT_FLAGS = SEGMENT_FLAGS or PF_X
else match =interpreter?, attribute
SEGMENT_TYPE = PT_INTERP
else match =dynamic?, attribute
SEGMENT_TYPE = PT_DYNAMIC
else match =note?, attribute
SEGMENT_TYPE = PT_NOTE
else match =gnustack?, attribute
SEGMENT_TYPE = PT_GNU_STACK
else match =gnuehframe?, attribute
SEGMENT_TYPE = PT_GNU_EH_FRAME
else match =gnurelro?, attribute
SEGMENT_TYPE = PT_GNU_RELRO
else
err 'unknown attribute "',`attribute,'"'
end match
end irpv
DEFINED_SEGMENT = 1
store SEGMENT_TYPE at ELF:p_type+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH
store SEGMENT_FLAGS at ELF:p_flags+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH
if SEGMENT_TYPE = PT_LOAD
store 1000h at ELF:p_align+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH
else
store 1 at ELF:p_align+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH
end if
end namespace
end macro
postpone
purge segment?
segment
namespace ELF
NUMBER_OF_SEGMENTS := SEGMENT_INDEX
end namespace
end postpone

View File

@ -0,0 +1,328 @@
macro format?.MZ?
format binary as 'exe'
include 'format/mz.inc'
include 'p6.inc'
end macro
macro format?.PE? settings
PE.Settings.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_32BIT_MACHINE or IMAGE_FILE_LINE_NUMS_STRIPPED or IMAGE_FILE_LOCAL_SYMS_STRIPPED
PE.Settings.DllCharacteristics = 0
local seq
define seq settings:
while 1
match :, seq
break
else match =DLL? more, seq
PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_DLL
redefine seq more
else match =large? more, seq
PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_LARGE_ADDRESS_AWARE
redefine seq more
else match =WDM? more, seq
PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_WDM_DRIVER
redefine seq more
else match =NX? more, seq
PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_NX_COMPAT
redefine seq more
else match =at? base =on? stub :, seq
PE.Settings.ImageBase = base
PE.Settings.Stub = stub
break
else match =at? base :, seq
PE.Settings.ImageBase = base
break
else match =on? stub :, seq
PE.Settings.Stub = stub
break
else
match =GUI? more, seq
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
redefine seq more
else match =console? more, seq
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
redefine seq more
else match =native? more, seq
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_NATIVE
PE.Settings.SectionAlignment = 32
PE.Settings.FileAlignment = 32
redefine seq more
else match =EFI? more, seq
PE.Settings.Magic = 0x20B
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION
redefine seq more
else match =EFIboot? more, seq
PE.Settings.Magic = 0x20B
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
redefine seq more
else match =EFIruntime? more, seq
PE.Settings.Magic = 0x20B
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
redefine seq more
else
err 'invalid argument'
break
end match
match V.v more, seq
PE.Settings.MajorSubsystemVersion = V
PE.Settings.MinorSubsystemVersion = v
redefine seq more
end match
end match
end while
if PE.Settings.Characteristics and IMAGE_FILE_DLL
format binary as 'dll'
else
format binary as 'exe'
end if
include 'format/pe.inc'
include 'p6.inc'
use32
end macro
macro format?.PE64? settings
PE.Settings.Magic = 0x20B
PE.Settings.Machine = IMAGE_FILE_MACHINE_AMD64
PE.Settings.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_LARGE_ADDRESS_AWARE or IMAGE_FILE_LINE_NUMS_STRIPPED or IMAGE_FILE_LOCAL_SYMS_STRIPPED
PE.Settings.DllCharacteristics = 0
PE.Settings.MajorSubsystemVersion = 5
PE.Settings.MinorSubsystemVersion = 0
local seq
define seq settings:
while 1
match :, seq
break
else match =DLL? more, seq
PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_DLL
redefine seq more
else match =WDM? more, seq
PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_WDM_DRIVER
redefine seq more
else match =NX? more, seq
PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_NX_COMPAT
redefine seq more
else match =at? base =on? stub :, seq
PE.Settings.ImageBase = base
PE.Settings.Stub = stub
break
else match =at? base :, seq
PE.Settings.ImageBase = base
break
else match =on? stub :, seq
PE.Settings.Stub = stub
break
else
match =GUI? more, seq
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
redefine seq more
else match =console? more, seq
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
redefine seq more
else match =native? more, seq
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_NATIVE
PE.Settings.SectionAlignment = 32
PE.Settings.FileAlignment = 32
redefine seq more
else match =EFI? more, seq
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION
redefine seq more
else match =EFIboot? more, seq
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
redefine seq more
else match =EFIruntime? more, seq
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
redefine seq more
else
err 'invalid argument'
break
end match
match V.v more, seq
PE.Settings.MajorSubsystemVersion = V
PE.Settings.MinorSubsystemVersion = v
redefine seq more
end match
end match
end while
if PE.Settings.Characteristics and IMAGE_FILE_DLL
format binary as 'dll'
else
format binary as 'exe'
end if
include 'format/pe.inc'
include 'x64.inc'
use64
end macro
macro format?.ELF? variant
match , variant
format binary as 'o'
include 'format/elf32.inc'
include 'p6.inc'
use32
else match =executable? settings, variant:
match brand =at? base:, settings
ELF.Settings.ABI = brand
ELF.Settings.BaseAddress = base
else match =at? base:, settings
ELF.Settings.BaseAddress = base
else match brand:, settings
ELF.Settings.ABI = brand
end match
include 'format/elfexe.inc'
include 'p6.inc'
use32
else match =dynamic? settings, variant:
ELF.Settings.Type = ET_DYN
match brand =at? base:, settings
ELF.Settings.ABI = brand
ELF.Settings.BaseAddress = base
else match =at? base:, settings
ELF.Settings.BaseAddress = base
else match brand:, settings
ELF.Settings.ABI = brand
end match
include 'format/elfexe.inc'
include 'p6.inc'
use32
else
err 'invalid argument'
end match
end macro
macro format?.ELF64? variant
match , variant
format binary as 'o'
include 'format/elf64.inc'
include 'x64.inc'
use64
else match =executable? settings, variant:
ELF.Settings.Class = ELFCLASS64
ELF.Settings.Machine = EM_X86_64
ELF.Settings.BaseAddress = 400000h
match brand =at? base:, settings
ELF.Settings.ABI = brand
ELF.Settings.BaseAddress = base
else match =at? base:, settings
ELF.Settings.BaseAddress = base
else match brand:, settings
ELF.Settings.ABI = brand
end match
include 'format/elfexe.inc'
include 'x64.inc'
use64
else match =dynamic? settings, variant:
ELF.Settings.Class = ELFCLASS64
ELF.Settings.Type = ET_DYN
ELF.Settings.Machine = EM_X86_64
ELF.Settings.BaseAddress = 400000h
match brand =at? base:, settings
ELF.Settings.ABI = brand
ELF.Settings.BaseAddress = base
else match =at? base:, settings
ELF.Settings.BaseAddress = base
else match brand:, settings
ELF.Settings.ABI = brand
end match
include 'format/elfexe.inc'
include 'x64.inc'
use64
else
err 'invalid argument'
end match
end macro
macro format?.ELFx32? variant
match , variant
format binary as 'o'
ELF.Settings.Machine = EM_X86_64
include 'format/elf32.inc'
include 'x64.inc'
use64
else match =executable? settings, variant:
ELF.Settings.Class = ELFCLASS32
ELF.Settings.Machine = EM_X86_64
ELF.Settings.BaseAddress = 400000h
match brand =at? base:, settings
ELF.Settings.ABI = brand
ELF.Settings.BaseAddress = base
else match =at? base:, settings
ELF.Settings.BaseAddress = base
else match brand:, settings
ELF.Settings.ABI = brand
end match
include 'format/elfexe.inc'
include 'x64.inc'
use64
else
err 'invalid argument'
end match
end macro
macro format?.COFF?
format binary as 'obj'
include 'format/coff.inc'
include 'p6.inc'
use32
end macro
macro format?.MS? variant
match =COFF?, variant
format binary as 'obj'
COFF.Settings.Characteristics = IMAGE_FILE_32BIT_MACHINE or IMAGE_FILE_LINE_NUMS_STRIPPED or IMAGE_FILE_BYTES_REVERSED_LO
include 'format/coffms.inc'
include 'p6.inc'
use32
else
err 'invalid argument'
end match
end macro
macro format?.MS64? variant
match =COFF?, variant
format binary as 'obj'
COFF.Settings.Machine = IMAGE_FILE_MACHINE_AMD64
COFF.Settings.Characteristics = IMAGE_FILE_32BIT_MACHINE or IMAGE_FILE_LINE_NUMS_STRIPPED or IMAGE_FILE_BYTES_REVERSED_LO
include 'format/coffms.inc'
include 'x64.inc'
use64
else
err 'invalid argument'
end match
end macro
macro format?.MachO? variant
match , variant
format binary as 'o'
MachO.Settings.FileType equ MH_OBJECT
include 'format/macho.inc'
include 'p6.inc'
use32
else match =executable?, variant
MachO.Settings.BaseAddress = 0x1000
include 'format/macho.inc'
include 'p6.inc'
use32
else
err 'invalid argument'
end match
end macro
macro format?.MachO64? variant
MachO.Settings.ProcessorType equ CPU_TYPE_X86_64
MachO.Settings.ProcessorSubtype equ CPU_SUBTYPE_X86_64_ALL
match , variant
format binary as 'o'
MachO.Settings.FileType equ MH_OBJECT
include 'format/macho.inc'
include 'x64.inc'
use64
else match =executable?, variant
MachO.Settings.BaseAddress = 0x100000000
include 'format/macho.inc'
include 'x64.inc'
use64
else
err 'invalid argument'
end match
end macro

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,209 @@
MZ::
.signature dw "MZ"
.bytes_in_last_page dw .LENGTH and 1FFh
.number_of_pages dw (.LENGTH-1) shr 9 + 1
.number_of_relocations dw .NUMBER_OF_RELOCATIONS
.number_of_header_paragraphs dw .HEADER_LENGTH shr 4
.minimum_heap dw (.LENGTH+.RESERVED_LENGTH-1) shr 4 - (.LENGTH-1) shr 4
.maximum_heap dw 0FFFFh
.initial_ss dw 0
.initial_sp dw 0
.checksum dw 0
.initial_ip dw 0
.initial_cs dw 0
.relocations_offset dw .relocations
.overlay_number dw 0
.relocations dw .NUMBER_OF_RELOCATIONS dup (?,?)
rb 0Fh - ($%+0Fh) and 0Fh
.HEADER_LENGTH = $
.RELOCATION_INDEX = 0
.ENTRY_DEFINED = 0
.HEAP_DEFINED = 0
.STACK_DEFINED = 0
.STACK_LENGTH = 1000h
org 0
macro entry? definition
local v
if MZ.ENTRY_DEFINED
err 'setting already specified'
else match seg:offs, definition
v = seg
if v relativeto MZ.segment
store v - MZ.segment : word at MZ : MZ.initial_cs
else
err 'incorrect segment'
end if
v = offs
if v >= 0 & v < 10000h
store v : word at MZ : MZ.initial_ip
else
err 'value out of range'
end if
MZ.ENTRY_DEFINED = 1
else
err 'invalid argument'
end match
end macro
macro heap? definition
local v,min
if MZ.HEAP_DEFINED
err 'setting already specified'
else
v = definition
if v >= 0 & v < 10000h
load min : word from MZ : MZ.minimum_heap
v = v + min
if v > 0FFFFh
v = 0FFFFh
end if
store v : word at MZ : MZ.maximum_heap
else
err 'value out of range'
end if
MZ.HEAP_DEFINED = 1
end if
end macro
macro stack? definition
local v
if MZ.STACK_DEFINED
err 'setting already specified'
else match seg:offs, definition
v = seg
if v relativeto MZ.segment
store v - MZ.segment : word at MZ : MZ.initial_ss
else
err 'incorrect segment'
end if
v = offs
if v >= 0 & v < 10000h
store v : word at MZ : MZ.initial_sp
else
err 'value out of range'
end if
MZ.STACK_DEFINED = 1
MZ.STACK_LENGTH = 0
else
MZ.STACK_DEFINED = 1
MZ.STACK_LENGTH = definition
end match
end macro
element MZ.segment
macro segment? definition
rb 0Fh - ($%+0Fh) and 0Fh
match name =use16?, definition
name := MZ.segment + ($%-MZ.HEADER_LENGTH) shr 4
use16
else match name =use32?, definition
name := MZ.segment + ($%-MZ.HEADER_LENGTH) shr 4
use32
else match name, definition
name := MZ.segment + ($%-MZ.HEADER_LENGTH) shr 4
end match
org 0
end macro
calminstruction calminstruction?.initsym? var*, val&
publish var, val
end calminstruction
calminstruction calminstruction?.asm? line&
local name, i
initsym name, name.0
match name.i, name
compute i, i+1
arrange name, name.i
publish name, line
arrange line, =assemble name
assemble line
end calminstruction
iterate <dw,word>, dw,word, dd,dword
calminstruction word? value
compute value, value
check value relativeto MZ.segment
jno plain
local offset
compute offset, $%
emit word, value - MZ.segment
check $% > offset
jno done
compute offset, offset - MZ.HEADER_LENGTH
compute offset, offset and 0FFFFh + (offset and not 0FFFFh) shl 12
asm store offset:4 at MZ : MZ.relocations + MZ.RELOCATION_INDEX shl 2
compute MZ.RELOCATION_INDEX, MZ.RELOCATION_INDEX + 1
done:
exit
plain:
emit word, value
end calminstruction
calminstruction dw? definitions&
local value, n
start:
match value=,definitions, definitions, ()
jyes recognize
match value, definitions
arrange definitions,
recognize:
match n =dup? value, value, ()
jyes duplicate
match ?, value
jyes reserve
call word, value
next:
match , definitions
jno start
take , definitions
take definitions, definitions
jyes next
exit
reserve:
emit word
jump next
duplicate:
match (value), value
stack:
check n
jno next
take definitions, value
arrange value, definitions
compute n, n - 1
jump stack
end calminstruction
calminstruction (label) dw? definitions&
local cmd
arrange cmd, =label label : =word
assemble cmd
arrange cmd, =dw definitions
assemble cmd
end calminstruction
end iterate
calminstruction align? boundary,value:?
compute boundary, (boundary-1)-((0 scaleof $)+boundary-1) mod boundary
arrange value, =db boundary =dup value
assemble value
end calminstruction
postpone
if MZ.STACK_LENGTH
rb 0Fh - ($%+0Fh) and 0Fh
store ($%-MZ.HEADER_LENGTH) shr 4 : word at MZ : MZ.initial_ss
rb MZ.STACK_LENGTH
store MZ.STACK_LENGTH : word at MZ : MZ.initial_sp
end if
MZ.LENGTH = $%%
MZ.RESERVED_LENGTH = $%-$%%
MZ.NUMBER_OF_RELOCATIONS = MZ.RELOCATION_INDEX
end postpone

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
calminstruction element? definition
local name, meta
match =tr? any, definition
jyes skip
arrange definition, =element? definition
assemble definition
skip:
end calminstruction
include '80486.inc'
purge element?
iterate <instr,opcode>, wrmsr,<0Fh,30h>, rdtsc,<0Fh,31h>, rdmsr,<0Fh,32h>, rdpmc,<0Fh,33h>, cpuid,<0Fh,0A2h>, rsm,<0Fh,0AAh>
calminstruction instr?
asm db opcode
end calminstruction
end iterate
calminstruction cmpxchg8b? dest*
call x86.parse_operand@dest, dest
check @dest.type = 'mem'
jyes operand_ok
err 'invalid operand'
exit
operand_ok:
check @dest.size and not 8
jno size_ok
err 'invalid operand size'
size_ok:
xcall x86.store_instruction@dest, <0Fh,0C7h>,(1)
end calminstruction
include '80387.inc'

View File

@ -0,0 +1,62 @@
include 'p5.inc'
iterate <instr,opcode>, sysenter,<0Fh,34h>, sysexit,<0Fh,35h>
calminstruction instr?
asm db opcode
end calminstruction
end iterate
iterate <cond,code>, o,0, no,1, c,2, b,2, nae,2, nc,3, nb,3, ae,3, z,4, e,4, nz,5, ne,5, na,6, be,6, a,7, nbe,7, \
s,8, ns,9, p,0Ah, pe,0Ah, np,0Bh, po,0Bh, l,0Ch, nge,0Ch, nl,0Dh, ge,0Dh, ng,0Eh, le,0Eh, g,0Fh, nle,0Fh
calminstruction cmov#cond? dest*,src*
call x86.parse_operand@dest, dest
call x86.parse_operand@src, src
check @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg')
jyes cmov_rm_reg
err 'invalid combination of operands'
exit
cmov_rm_reg:
check @src.size and not @dest.size
jno cmov_rm_reg_ok
err 'operand sizes do not match'
cmov_rm_reg_ok:
call x86.select_operand_prefix@src, @dest.size
xcall x86.store_instruction@src, <0Fh,40h+code>,@dest.rm
end calminstruction
end iterate
iterate <instr,opcode>, fcmovb,<0DAh,0C0h>, fcmove,<0DAh,0C8h>, fcmovbe,<0DAh,0D0h>, fcmovu,<0DAh,0D8h>, \
fcmovnb,<0DBh,0C0h>, fcmovne,<0DBh,0C8h>, fcmovnbe,<0DBh,0D0h>, fcmovnu,<0DBh,0D8h>
calminstruction instr? dest*,src*
call x87.parse_operand@dest, dest
call x87.parse_operand@src, src
check @dest.type = 'streg' & @dest.rm = 0 & @src.type = 'streg'
jyes ok
err 'invalid operand'
exit
ok:
asm db opcode + @src.rm
end calminstruction
end iterate
iterate <instr,opcode,postbyte>, fucomi,0DBh,5, fucomip,0DFh,5, fcomi,0DBh,6, fcomip,0DFh,6
calminstruction instr? src:st1
call x87.parse_operand@src, src
check @src.type = 'streg'
jyes ok
err 'invalid operand'
exit
ok:
emit 1, opcode
emit 1, 11b shl 6 + postbyte shl 3 + @src.rm
end calminstruction
end iterate

File diff suppressed because it is too large Load Diff