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 , 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 , 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 , 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 , 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 , 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 , 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 , 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 , 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 , 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 , 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