555 lines
12 KiB
PHP
555 lines
12 KiB
PHP
|
|
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 |