mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-27 05:32:28 +02:00
+ first commit (nothing compilable, still needs to be made more OOP)
This commit is contained in:
parent
ec34af8955
commit
0284ece771
624
compiler/new/aopt/ao386msc.pas
Normal file
624
compiler/new/aopt/ao386msc.pas
Normal file
@ -0,0 +1,624 @@
|
||||
Unit ao386msc;
|
||||
|
||||
Interface
|
||||
|
||||
uses i386base;
|
||||
|
||||
{ enable the following define if memory references can have both a base and }
|
||||
{ index register in 1 operand }
|
||||
|
||||
{$define RefsHaveIndexReg}
|
||||
|
||||
{ enable the following define if memory references can have a scaled index }
|
||||
|
||||
{$define RefsHaveScale}
|
||||
|
||||
{ enable the following define if memory references can have a segment }
|
||||
{ override }
|
||||
|
||||
{$define RefsHaveSegment}
|
||||
|
||||
{ enable the following define if memory references can have a symbol }
|
||||
{ value }
|
||||
|
||||
{$define RefsHaveSymbol}
|
||||
|
||||
|
||||
Type
|
||||
|
||||
{possible actions on an operand: read, write or modify (= read & write)}
|
||||
TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
|
||||
|
||||
{ type of a normal instruction }
|
||||
TInstr = Tai386;
|
||||
PInstr = ^TInstr;
|
||||
|
||||
TFlag = (DirFlag);
|
||||
|
||||
TFlagContents = (F_Unknown, F_Clear, F_Set);
|
||||
|
||||
TCondRegs = Object
|
||||
Flags: Array[TFlag] of TFlagContents;
|
||||
Constructor Init;
|
||||
Procedure InitFlag(f: TFlag);
|
||||
Procedure SetFlag(f: TFlag);
|
||||
Procedure ClearFlag(f: TFlag);
|
||||
Function GetFlag(f: TFlag): TFlagContents;
|
||||
End;
|
||||
|
||||
{What an instruction can change}
|
||||
TChange = (C_None,
|
||||
{Read from a register}
|
||||
C_REAX, C_RECX, C_REDX, C_REBX, C_RESP, C_REBP, C_RESI, C_REDI,
|
||||
{write from a register}
|
||||
C_WEAX, C_WECX, C_WEDX, C_WEBX, C_WESP, C_WEBP, C_WESI, C_WEDI,
|
||||
{read and write from/to a register}
|
||||
C_RWEAX, C_RWECX, C_RWEDX, C_RWEBX, C_RWESP, C_RWEBP, C_RWESI, C_RWEDI,
|
||||
{modify the contents of a register with the purpose of using
|
||||
this changed content afterwards (add/sub/..., but e.g. not rep
|
||||
or movsd)}
|
||||
{$ifdef arithopt}
|
||||
C_MEAX, C_MECX, C_MEDX, C_MEBX, C_MESP, C_MEBP, C_MESI, C_MEDI,
|
||||
{$endif arithopt}
|
||||
C_CDirFlag {clear direction flag}, C_SDirFlag {set dir flag},
|
||||
C_RFlags, C_WFlags, C_RWFlags, C_FPU,
|
||||
C_Rop1, C_Wop1, C_RWop1,
|
||||
C_Rop2, C_Wop2, C_RWop2,
|
||||
C_Rop3, C_WOp3, C_RWOp3,
|
||||
{$ifdef arithopt}
|
||||
C_Mop1, C_Mop2, C_Mop3,
|
||||
{$endif arithopt}
|
||||
C_WMemEDI,
|
||||
C_All);
|
||||
|
||||
|
||||
Const
|
||||
|
||||
{$ifndef arithopt}
|
||||
C_MEAX = C_RWEAX;
|
||||
C_MECX = C_RWECX;
|
||||
C_MEDX = C_RWEDX;
|
||||
C_MEBX = C_RWEBX;
|
||||
C_MESP = C_RWESP;
|
||||
C_MEBP = C_RWEBP;
|
||||
C_MESI = C_RWESI;
|
||||
C_MEDI = C_RWEDI;
|
||||
C_Mop1 = C_RWOp1;
|
||||
C_Mop2 = C_RWOp2;
|
||||
C_Mop3 = C_RWOp3;
|
||||
{$endif arithopt}
|
||||
|
||||
{ the maximum number of things (registers, memory, ...) a single instruction }
|
||||
{ changes }
|
||||
|
||||
MaxCh = 3;
|
||||
|
||||
{ the maximum number of operands an instruction has }
|
||||
|
||||
MaxOps = 3;
|
||||
|
||||
{Oper index of operand that contains the source (reference) with a load }
|
||||
{instruction }
|
||||
|
||||
LoadSrc = 0;
|
||||
|
||||
{Oper index of operand that contains the destination (register) with a load }
|
||||
{instruction }
|
||||
|
||||
LoadDst = 1;
|
||||
|
||||
{Oper index of operand that contains the source (register) with a store }
|
||||
{instruction }
|
||||
|
||||
StoreSrc = 0;
|
||||
|
||||
{Oper index of operand that contains the destination (reference) with a load }
|
||||
{instruction }
|
||||
|
||||
StoreDst = 1;
|
||||
|
||||
|
||||
|
||||
{ low and high maximum width general purpose register }
|
||||
LoGPReg = R_EAX;
|
||||
HiGPReg = R_EDI;
|
||||
|
||||
{ low and high of every possible width general purpose register (same as }
|
||||
{ above on most architctures apart from the 80x86) }
|
||||
LoReg = R_EAX;
|
||||
HiReg = R_BL;
|
||||
|
||||
{ Stack pointer }
|
||||
StackPtr = R_ESP;
|
||||
|
||||
Const AsmInstr: Array[tasmop] Of TAsmInstrucProp = (
|
||||
{A_<NONE>} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_LOCK} (Ch: (C_None, C_None, C_None)),
|
||||
{A_REP} (Ch: (C_RWECX, C_RFlags, C_None)),
|
||||
{A_REPE} (Ch: (C_RWECX, C_RFlags, C_None)),
|
||||
{A_REPNE} (Ch: (C_RWECX, C_RFlags, C_None)),
|
||||
{A_REPNZ} (Ch: (C_WECX, C_RWFLAGS, C_None)), { new }
|
||||
{A_REPZ} (Ch: (C_WECX, C_RWFLAGS, C_None)), { new }
|
||||
{A_SEGCS} (Ch: (C_None, C_None, C_None)), { new }
|
||||
{A_SEGES} (Ch: (C_None, C_None, C_None)), { new }
|
||||
{A_SEGDS} (Ch: (C_None, C_None, C_None)), { new }
|
||||
{A_SEGFS} (Ch: (C_None, C_None, C_None)), { new }
|
||||
{A_SEGGS} (Ch: (C_None, C_None, C_None)), { new }
|
||||
{A_SEGSS} (Ch: (C_None, C_None, C_None)), { new }
|
||||
{A_AAA} (Ch: (C_MEAX, C_WFlags, C_None)),
|
||||
{A_AAD} (Ch: (C_MEAX, C_WFlags, C_None)),
|
||||
{A_AAM} (Ch: (C_MEAX, C_WFlags, C_None)),
|
||||
{A_AAS} (Ch: (C_MEAX, C_WFlags, C_None)),
|
||||
{A_ADC} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
|
||||
{A_ADD} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
|
||||
{A_AND} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
|
||||
{A_ARPL} (Ch: (C_WFlags, C_None, C_None)),
|
||||
{A_BOUND} (Ch: (C_Rop1, C_None, C_None)),
|
||||
{A_BSF} (Ch: (C_Wop2, C_WFlags, C_Rop1)),
|
||||
{A_BSR} (Ch: (C_Wop2, C_WFlags, C_Rop1)),
|
||||
{A_BSWAP} (Ch: (C_MOp1, C_None, C_None)), { new }
|
||||
{A_BT} (Ch: (C_WFlags, C_Rop1, C_None)),
|
||||
{A_BTC} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
|
||||
{A_BTR} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
|
||||
{A_BTS} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
|
||||
{A_CALL} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
|
||||
{A_CBW} (Ch: (C_MEAX, C_None, C_None)),
|
||||
{A_CDQ} (Ch: (C_MEAX, C_WEDX, C_None)),
|
||||
{A_CLC} (Ch: (C_WFlags, C_None, C_None)),
|
||||
{A_CLD} (Ch: (C_CDirFlag, C_None, C_None)),
|
||||
{A_CLI} (Ch: (C_WFlags, C_None, C_None)),
|
||||
{A_CLTS} (Ch: (C_None, C_None, C_None)),
|
||||
{A_CMC} (Ch: (C_WFlags, C_None, C_None)),
|
||||
{A_CMP} (Ch: (C_WFlags, C_None, C_None)),
|
||||
{A_CMPSB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_CMPSD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_CMPSW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_CMPXCHG} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_CMPXCHG486} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_CMPXCHG8B} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_CPUID} (Ch: (C_All, C_None, C_none)),
|
||||
{A_CWD} (Ch: (C_MEAX, C_WEDX, C_None)),
|
||||
{A_CWDE} (Ch: (C_MEAX, C_None, C_None)),
|
||||
{A_DAA} (Ch: (C_MEAX, C_None, C_None)),
|
||||
{A_DAS} (Ch: (C_MEAX, C_None, C_None)),
|
||||
{A_DEC} (Ch: (C_Mop1, C_WFlags, C_None)),
|
||||
{A_DIV} (Ch: (C_RWEAX, C_WEDX, C_WFlags)),
|
||||
{A_EMMS} (Ch: (C_FPU, C_None, C_None)), { new }
|
||||
{A_ENTER} (Ch: (C_RWESP, C_None, C_None)),
|
||||
{A_EQU} (Ch: (C_None, C_None, C_None)), { new }
|
||||
{A_F2XM1} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FABS} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FADD} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FADDP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FBLD} (Ch: (C_Rop1, C_FPU, C_None)),
|
||||
{A_FBSTP} (Ch: (C_Wop1, C_FPU, C_None)),
|
||||
{A_FCHS} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FCLEX} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FCMOVB} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
|
||||
{A_FCMOVBE} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
|
||||
{A_FCMOVE} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
|
||||
{A_FCMOVNB} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
|
||||
{A_FCMOVNBE} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
|
||||
{A_FCMOVNE} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
|
||||
{A_FCMOVNU} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
|
||||
{A_FCMOVU} (Ch: (C_FPU, C_RFLAGS, C_None)), { new }
|
||||
{A_FCOM} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FCOMI} (Ch: (C_WFLAGS, C_None, C_None)), { new }
|
||||
{A_FCOMIP} (Ch: (C_FPU, C_WFLAGS, C_None)), { new }
|
||||
{A_FCOMP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FCOMPP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FCOS} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FDECSTP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FDISI} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FDIV} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FDIVP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FDIVR} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FDIVRP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FEMMS} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_FENI} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FFREE} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FIADD} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FICOM} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FICOMP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FIDIV} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FIDIVR} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FILD} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FIMUL} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FINCSTP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FINIT} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FIST} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_FISTP} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_FISUB} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FISUBR} (Ch: (C_FPU, C_None, C_None)), { new }
|
||||
{A_FLD} (Ch: (C_Rop1, C_FPU, C_None)),
|
||||
{A_FLD1} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FLDCW} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FLDENV} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FLDL2E} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FLDL2T} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FLDLG2} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FLDLN2} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FLDPI} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FLDZ} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FMUL} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FMULP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FNCLEX} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FNDISI} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FNENI} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FNINIT} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FNOP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FNSAVE} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FNSTCW} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_FNSTENV} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_FNSTSW} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_FPATAN} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FPREM} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FPREM1} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FPTAN} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FRNDINT} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FRSTOR} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FSAVE} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_FSCALE} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FSETPM} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FSIN} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FSINCOS} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FSQRT} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FST} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_FSTCW} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_FSTENV} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_FSTP} (Ch: (C_Wop1, C_FPU, C_None)),
|
||||
{A_FSTSW} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_FSUB} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FSUBP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FSUBR} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FSUBRP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FTST} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FUCOM} (Ch: (C_None, C_None, C_None)), {changes fpu status word}
|
||||
{A_FUCOMI} (Ch: (C_WFLAGS, C_None, C_None)), { new }
|
||||
{A_FUCOMIP} (Ch: (C_FPU, C_WFLAGS, C_None)), { new }
|
||||
{A_FUCOMP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FUCOMPP} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FWAIT} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FXAM} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FXCH} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FXTRACT} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FYL2X} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_FYL2XP1} (Ch: (C_FPU, C_None, C_None)),
|
||||
{A_HLT} (Ch: (C_None, C_None, C_None)),
|
||||
{A_IBTS} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_ICEBP} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_IDIV} (Ch: (C_RWEAX, C_WEDX, C_WFlags)), {handled separately, because modifies more than three things}
|
||||
{A_IMUL} (Ch: (C_RWEAX, C_WEDX, C_WFlags)), {handled separately, because several forms exist}
|
||||
{A_IN} (Ch: (C_Wop2, C_Rop1, C_None)),
|
||||
{A_INC} (Ch: (C_Mop1, C_WFlags, C_None)),
|
||||
{A_INSB} (Ch: (C_WMemEDI, C_RWEDI, C_None)), { new }
|
||||
{A_INSD} (Ch: (C_WMemEDI, C_RWEDI, C_None)), { new }
|
||||
{A_INSW} (Ch: (C_WMemEDI, C_RWEDI, C_None)), { new }
|
||||
{A_INT} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
|
||||
{A_INT01} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_INT1} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_INT3} (Ch: (C_None, C_None, C_None)),
|
||||
{A_INTO} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
|
||||
{A_INVD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_INVLPG} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_IRET} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
|
||||
{A_IRETD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_IRETW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_JCXZ} (Ch: (C_RECX, C_None, C_None)),
|
||||
{A_JECXZ} (Ch: (C_RECX, C_None, C_None)),
|
||||
{A_JMP} (Ch: (C_None, C_None, C_None)),
|
||||
{A_LAHF} (Ch: (C_WEAX, C_RFlags, C_None)),
|
||||
{A_LAR} (Ch: (C_Wop2, C_None, C_None)),
|
||||
{A_LDS} (Ch: (C_Wop2, C_None, C_None)),
|
||||
{A_LEA} (Ch: (C_Wop2, C_Rop1, C_None)),
|
||||
{A_LEAVE} (Ch: (C_RWESP, C_None, C_None)),
|
||||
{A_LES} (Ch: (C_Wop2, C_None, C_None)),
|
||||
{A_LFS} (Ch: (C_Wop2, C_None, C_None)),
|
||||
{A_LGDT} (Ch: (C_None, C_None, C_None)),
|
||||
{A_LGS} (Ch: (C_Wop2, C_None, C_None)),
|
||||
{A_LIDT} (Ch: (C_None, C_None, C_None)),
|
||||
{A_LLDT} (Ch: (C_None, C_None, C_None)),
|
||||
{A_LMSW} (Ch: (C_None, C_None, C_None)),
|
||||
{A_LOADALL} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_LOADALL286} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_LODSB} (Ch: (C_WEAX, C_RWESI, C_None)), { new }
|
||||
{A_LODSD} (Ch: (C_WEAX, C_RWESI, C_None)), { new }
|
||||
{A_LODSW} (Ch: (C_WEAX, C_RWESI, C_None)), { new }
|
||||
{A_LOOP} (Ch: (C_RWECX, C_None, C_None)),
|
||||
{A_LOOPE} (Ch: (C_RWECX, C_RFlags, C_None)),
|
||||
{A_LOOPNE} (Ch: (C_RWECX, C_RFlags, C_None)),
|
||||
{A_LOOPNZ} (Ch: (C_RWECX, C_RFlags, C_None)),
|
||||
{A_LOOPZ} (Ch: (C_RWECX, C_RFlags, C_None)),
|
||||
{A_LSL} (Ch: (C_Wop2, C_WFlags, C_None)),
|
||||
{A_LSS} (Ch: (C_Wop2, C_None, C_None)),
|
||||
{A_LTR} (Ch: (C_None, C_None, C_None)),
|
||||
{A_MOV} (Ch: (C_Wop2, C_Rop1, C_None)),
|
||||
{A_MOVD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_MOVQ} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_MOVSB} (Ch: (C_All, C_Rop1, C_None)),
|
||||
{A_MOVSD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_MOVSW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_MOVSX} (Ch: (C_Wop2, C_Rop1, C_None)),
|
||||
{A_MOVZX} (Ch: (C_Wop2, C_Rop1, C_None)),
|
||||
{A_MUL} (Ch: (C_RWEAX, C_WEDX, C_WFlags)), {handled separately, because modifies more than three things}
|
||||
{A_NEG} (Ch: (C_Mop1, C_None, C_None)),
|
||||
{A_NOP} (Ch: (C_None, C_None, C_None)),
|
||||
{A_NOT} (Ch: (C_Mop1, C_WFlags, C_None)),
|
||||
{A_OR} (Ch: (C_Mop2, C_WFlags, C_None)),
|
||||
{A_OUT} (Ch: (C_Rop1, C_Rop2, C_None)),
|
||||
{A_OUTSB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_OUTSD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_OUTSW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PACKSSDW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PACKSSWB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PACKUSWB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PADDB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PADDD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PADDSB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PADDSIW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PADDSW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PADDUSB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PADDUSW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PADDW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PAND} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PANDN} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PAVEB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PAVGUSB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PCMPEQB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PCMPEQD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PCMPEQW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PCMPGTB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PCMPGTD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PCMPGTW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PDISTIB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PF2ID} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFACC} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFADD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFCMPEQ} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFCMPGE} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFCMPGT} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFMAX} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFMIN} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFMUL} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFRCP} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFRCPIT1} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFRCPIT2} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFRSQIT1} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFRSQRT} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFSUB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PFSUBR} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PI2FD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PMACHRIW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PMADDWD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PMAGW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PMULHRIW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PMULHRWA} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PMULHRWC} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PMULHW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PMULLW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PMVGEZB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PMVLZB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PMVNZB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PMVZB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_POP} (Ch: (C_Wop1, C_RWESP, C_None)),
|
||||
{A_POPA} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
|
||||
{A_POPAD} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
|
||||
{A_POPAW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_POPF} (Ch: (C_RWESP, C_WFlags, C_None)),
|
||||
{A_POPFD} (Ch: (C_RWESP, C_WFlags, C_None)),
|
||||
{A_POPFW} (Ch: (C_RWESP, C_WFLAGS, C_None)), { new }
|
||||
{A_POR} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PREFETCH} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PREFETCHW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSLLD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSLLQ} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSLLW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSRAD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSRAW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSRLD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSRLQ} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSRLW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSUBB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSUBD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSUBSB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSUBSIW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSUBSW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSUBUSB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSUBUSW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PSUBW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PUNPCKHBW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PUNPCKHDQ} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PUNPCKHWD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PUNPCKLBW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PUNPCKLDQ} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PUNPCKLWD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PUSH} (Ch: (C_Rop1, C_RWESP, C_None)),
|
||||
{A_PUSHA} (Ch: (C_All, C_None, C_None)),
|
||||
{A_PUSHAD} (Ch: (C_All, C_None, C_None)),
|
||||
{A_PUSHAW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_PUSHF} (Ch: (C_RWESP, C_RFlags, C_None)),
|
||||
{A_PUSHFD} (Ch: (C_RWESP, C_RFlags, C_None)),
|
||||
{A_PUSHFW} (Ch: (C_RWESP, C_RFLAGS, C_None)), { new }
|
||||
{A_PXOR} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_RCL} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
|
||||
{A_RCR} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
|
||||
{A_RDMSR} (Ch: (C_WEAX, C_WEDX, C_None)), { new }
|
||||
{A_RDPMC} (Ch: (C_WEAX, C_WEDX, C_None)), { new }
|
||||
{A_RDTSC} (Ch: (C_WEAX, C_WEDX, C_None)), { new }
|
||||
{A_RESB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_RET} (Ch: (C_All, C_None, C_None)),
|
||||
{A_RETF} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_RETN} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_ROL} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
|
||||
{A_ROR} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
|
||||
{A_RSM} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_SAHF} (Ch: (C_WFlags, C_REAX, C_None)),
|
||||
{A_SAL} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
|
||||
{A_SALC} (Ch: (C_WEAX, C_RFLAGS, C_None)), { new }
|
||||
{A_SAR} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
|
||||
{A_SBB} (Ch: (C_Mop2, C_Rop1, C_RWFlags)),
|
||||
{A_SCASB} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_SCASD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_SCASW} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_SGDT} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_SHL} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
|
||||
{A_SHLD} (Ch: (C_MOp3, C_RWFlags, C_Rop2)),
|
||||
{A_SHR} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
|
||||
{A_SHRD} (Ch: (C_MOp3, C_RWFlags, C_Rop2)),
|
||||
{A_SIDT} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_SLDT} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_SMI} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_SMSW} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_STC} (Ch: (C_WFlags, C_None, C_None)),
|
||||
{A_STD} (Ch: (C_SDirFlag, C_None, C_None)),
|
||||
{A_STI} (Ch: (C_WFlags, C_None, C_None)),
|
||||
{A_STOSB} (Ch: (C_REAX, C_WMemEDI, C_RWEDI)), { new }
|
||||
{A_STOSD} (Ch: (C_REAX, C_WMemEDI, C_RWEDI)), { new }
|
||||
{A_STOSW} (Ch: (C_REAX, C_WMemEDI, C_RWEDI)), { new }
|
||||
{A_STR} (Ch: (C_Wop1, C_None, C_None)),
|
||||
{A_SUB} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
|
||||
{A_TEST} (Ch: (C_WFlags, C_Rop1, C_Rop2)),
|
||||
{A_UMOV} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_VERR} (Ch: (C_WFlags, C_None, C_None)),
|
||||
{A_VERW} (Ch: (C_WFlags, C_None, C_None)),
|
||||
{A_WAIT} (Ch: (C_None, C_None, C_None)),
|
||||
{A_WBINVD} (Ch: (C_None, C_None, C_None)), { new }
|
||||
{A_WRMSR} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_XADD} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_XBTS} (Ch: (C_All, C_None, C_None)), { new }
|
||||
{A_XCHG} (Ch: (C_RWop1, C_RWop2, C_None)), {(might be) handled seperately}
|
||||
{A_XLAT} (Ch: (C_WEAX, C_REBX, C_None)),
|
||||
{A_XLATB} (Ch: (C_WEAX, C_REBX, C_None)),
|
||||
{A_XOR} (Ch: (C_Mop2, C_Rop1, C_WFlags)),
|
||||
{A_CMOV} (Ch: (C_ROp1, C_WOp2, C_RFLAGS)), { new }
|
||||
{A_J} (Ch: (C_None, C_None, C_None)), { new }
|
||||
{A_SET} (Ch: (C_WEAX, C_RFLAGS, C_None)) { new }
|
||||
);
|
||||
|
||||
|
||||
Function RegMaxSize(Reg: TRegister): TRegister;
|
||||
Function RegsSameSize(Reg1, Reg2: TRegister): Boolean;
|
||||
Function IsLoadInstr(p: pai): Boolean;
|
||||
|
||||
Implementation
|
||||
|
||||
{************************ TCondRegs ************************}
|
||||
|
||||
Constructor TCondRegs.init;
|
||||
Begin
|
||||
FillChar(Flags, SizeOf(Flags), Byte(F_Unknown))
|
||||
End;
|
||||
|
||||
Procedure TCondRegs.InitFlag(f: TFlag);
|
||||
Begin
|
||||
Flags[f] := F_Unknown
|
||||
End;
|
||||
|
||||
Procedure TCondRegs.SetFlag(f: TFlag);
|
||||
Begin
|
||||
Flags[f] := F_Set
|
||||
End;
|
||||
|
||||
Procedure TCondRegs.ClearFlag(f: TFlag);
|
||||
Begin
|
||||
Flags[f] : =F_Clear
|
||||
End;
|
||||
|
||||
Function GetFlag(f: TFlag): TFlagContents;
|
||||
Begin
|
||||
GetFlag := Flags[f]
|
||||
End;
|
||||
|
||||
{*************************************************************}
|
||||
|
||||
Function RegMaxSize(Reg: TRegister): TRegister;
|
||||
{Returns the 32 bit component of Reg if it exists, otherwise Reg is returned}
|
||||
Begin
|
||||
RegMaxSize := Reg;
|
||||
If (Reg >= R_AX)
|
||||
Then
|
||||
If (Reg <= R_DI)
|
||||
Then RegMaxSize := Reg16ToReg32(Reg)
|
||||
Else
|
||||
If (Reg <= R_BL)
|
||||
Then RegMaxSize := Reg8toReg32(Reg);
|
||||
End;
|
||||
|
||||
Function RegsSameSize(Reg1, Reg2: TRegister): Boolean;
|
||||
{returns true if Reg1 and Reg2 are of the same size (so if they're both
|
||||
8bit, 16bit or 32bit)}
|
||||
Begin
|
||||
If (Reg1 <= R_EDI)
|
||||
Then RegsSameSize := (Reg2 <= R_EDI)
|
||||
Else
|
||||
If (Reg1 <= R_DI)
|
||||
Then RegsSameSize := (Reg2 in [R_AX..R_DI])
|
||||
Else
|
||||
If (Reg1 <= R_BL)
|
||||
Then RegsSameSize := (Reg2 in [R_AL..R_BL])
|
||||
Else RegsSameSize := False
|
||||
End;
|
||||
|
||||
Function IsLoadInstr(p: pai): Boolean;
|
||||
{ returns true if p is a load instruction (loads value from memory in a }
|
||||
{ register) }
|
||||
Begin
|
||||
IsLoadInstr :=
|
||||
(p^.typ = ait_instruction) and
|
||||
((PInstr(p)^.OpCode = A_MOV) or
|
||||
(PInstr(p)^.OpCode = A_MOVZX) or
|
||||
(PInstr(p)^.OpCode = A_MOVSX)) And
|
||||
(PInstr(p)^.oper[LoadSrc].typ = top_ref));
|
||||
End;
|
||||
|
||||
Function IsStoreInstr(p: pai): Boolean;
|
||||
{ returns true if p is a load instruction (loads value from memory in a }
|
||||
{ register) }
|
||||
Begin
|
||||
IsLoadInstr :=
|
||||
(p^.typ = ait_instruction) and
|
||||
((PInstr(p)^.OpCode = A_MOV) or
|
||||
(PInstr(p)^.OpCode = A_MOVZX) or
|
||||
(PInstr(p)^.OpCode = A_MOVSX)) And
|
||||
(PInstr(p)^.oper[StoreDst].typ = top_ref));
|
||||
End;
|
||||
|
||||
|
||||
Function TCh2Reg(Ch: TChange): TRegister;
|
||||
{converts a TChange variable to a TRegister}
|
||||
Begin
|
||||
If (Ch <= C_REDI) Then
|
||||
TCh2Reg := TRegister(Byte(Ch))
|
||||
Else
|
||||
If (Ch <= C_WEDI) Then
|
||||
TCh2Reg := TRegister(Byte(Ch) - Byte(C_REDI))
|
||||
Else
|
||||
If (Ch <= C_RWEDI) Then
|
||||
TCh2Reg := TRegister(Byte(Ch) - Byte(C_WEDI))
|
||||
Else InternalError($db)
|
||||
End;
|
||||
|
||||
Function RegReadByInstr(Reg: TRegister; p: Pai);
|
||||
Begin
|
||||
RegReadByInstr := False;
|
||||
If (p^.typ = ait_instruction) Then
|
||||
Case p^.opcode of
|
||||
A_IMUL:
|
||||
With PInstr(p)^ Do
|
||||
RegReadByInstr :=
|
||||
RegInOp(Reg,op[0]) or
|
||||
RegInOp(Reg,op[1]) or
|
||||
((op[1]^.typ = top_none) and
|
||||
(op[2]^.typ = top_none) and
|
||||
(reg in [R_EAX,R_EDX]))
|
||||
A_IDIV, A_MUL:
|
||||
RegReadByInstr :=
|
||||
RegInOp(Reg,op[0]) or
|
||||
(Reg = R_EAX) or
|
||||
((Reg = R_EDX) and
|
||||
(p^.opcode = A_IDIV) and
|
||||
(p^.size = S_L));
|
||||
|
||||
|
||||
|
||||
End.
|
97
compiler/new/aopt/aopt.pas
Normal file
97
compiler/new/aopt/aopt.pas
Normal file
@ -0,0 +1,97 @@
|
||||
Unit aopt;
|
||||
|
||||
Interface
|
||||
|
||||
Uses Aasm, cobjects, aoptmsc, aoptda, aoptcs, aoptpeep
|
||||
{$ifdef i386}
|
||||
, ao386msc;
|
||||
{$endif i386}
|
||||
|
||||
|
||||
Type
|
||||
|
||||
TAsmOptimizer = Object
|
||||
{ the PAasmOutput list this optimizer instance works on }
|
||||
AsmL: PAasmOutput;
|
||||
|
||||
{ The labeltable contains the addresses of the Pai objects that are labels }
|
||||
LabelInfo: PLabelInfo;
|
||||
|
||||
{ Start and end of the block that is currently being optimized, initialized }
|
||||
{ by InitDFA }
|
||||
|
||||
BlockStart, BlockEnd: Pai;
|
||||
|
||||
{ How many instructions are between the current instruction and the last one }
|
||||
{ that modified the register }
|
||||
NrOfInstrSinceLastMod: TInstrSinceLastMod;
|
||||
|
||||
|
||||
{ _AsmL is the PAasmOutpout list that has to be optimized }
|
||||
Constructor Init(_AsmL: PAasmOutput);
|
||||
|
||||
{ general, processor independent procedures }
|
||||
|
||||
{ general, processor dependent procedures }
|
||||
|
||||
Implementation
|
||||
|
||||
Constructor TAsmOptimizer.Init(_AsmL: PAasmOutput);
|
||||
Begin
|
||||
AsmL := _AsmL;
|
||||
End;
|
||||
|
||||
Procedure Optimize;
|
||||
Var HP: Pai;
|
||||
AsmDFA: TAsmDFA;
|
||||
Begin
|
||||
{setup labeltable, always necessary}
|
||||
BlockStart := Pai(AsmL^.First);
|
||||
AsmDFA.Init(AsmL, BlockStart, BlockEnd);
|
||||
{Blockend now either contains an ait_marker with Kind = AsmBlockStart, or nil}
|
||||
While Assigned(BlockStart) Do
|
||||
Begin
|
||||
LabelInfo := AsmDFA.GetLabelInfo;
|
||||
{ peephole optimizations, twice }
|
||||
PeepHoleOptPass1;
|
||||
PeepHoleOptPass1;
|
||||
If (cs_slowoptimize in aktglobalswitches) Then
|
||||
Begin
|
||||
{ data flow analyzer }
|
||||
DFAPass2;
|
||||
{ common subexpression elimination }
|
||||
CSE;
|
||||
End;
|
||||
{ more peephole optimizations }
|
||||
PeepHoleOptPass2;
|
||||
{dispose labeltabel}
|
||||
AsmDFA.Done;
|
||||
{continue where we left off, BlockEnd is either the start of an assembler
|
||||
block or nil}
|
||||
BlockStart := BlockEnd;
|
||||
While Assigned(BlockStart) And
|
||||
(BlockStart^.typ = ait_Marker) And
|
||||
(Pai_Marker(BlockStart)^.Kind = AsmBlockStart) Do
|
||||
Begin
|
||||
{we stopped at an assembler block, so skip it}
|
||||
While GetNextInstruction(BlockStart, BlockStart) And
|
||||
((BlockStart^.Typ <> Ait_Marker) Or
|
||||
(Pai_Marker(Blockstart)^.Kind <> AsmBlockEnd)) Do;
|
||||
{blockstart now contains a pai_marker(asmblockend)}
|
||||
If GetNextInstruction(BlockStart, HP) And
|
||||
((HP^.typ <> ait_Marker) Or
|
||||
(Pai_Marker(HP)^.Kind <> AsmBlockStart)) Then
|
||||
{there is no assembler block anymore after the current one, so
|
||||
optimize the next block of "normal" instructions}
|
||||
AsmDFA.Init(AsmL, BlockStart, BlockEnd);
|
||||
{otherwise, skip the next assembler block}
|
||||
Else BlockStart := HP;
|
||||
End
|
||||
End;
|
||||
End;
|
||||
|
||||
Destructor TAsmOptimizer.Done;
|
||||
Begin
|
||||
End;
|
||||
|
||||
{Virtual methods, most have to be overridden by processor dependent methods}
|
24
compiler/new/aopt/aopt386.pas
Normal file
24
compiler/new/aopt/aopt386.pas
Normal file
@ -0,0 +1,24 @@
|
||||
unit aopt386;
|
||||
|
||||
Interface
|
||||
|
||||
uses aopt;
|
||||
|
||||
Type TAsmOptimizer386 = Object(TAsmOptimizer)
|
||||
Constructor Init(_AsmL: PAasmOutput);
|
||||
Destructor done;
|
||||
End;
|
||||
|
||||
Implementation
|
||||
|
||||
Constructor init(_AsmL: PAasmOutput);
|
||||
begin
|
||||
inherited init(_AsmL);
|
||||
End;
|
||||
|
||||
Destructor Done;
|
||||
Begin
|
||||
inherited done
|
||||
End;
|
||||
|
||||
End.
|
581
compiler/new/aopt/aoptda.pas
Normal file
581
compiler/new/aopt/aoptda.pas
Normal file
@ -0,0 +1,581 @@
|
||||
Unit aoptda;
|
||||
|
||||
Interface
|
||||
|
||||
uses Aasm;
|
||||
|
||||
Type TAsmDFA = Object
|
||||
Constructor Init(_AsmL: PaasmOutPut; _Blockstart, _Blockend: Pai);
|
||||
{ returns a pointer to the LabelInfo table }
|
||||
Function GetLabelInfo: PLabelInfo;
|
||||
Destructor Done;
|
||||
|
||||
private
|
||||
|
||||
AsmL: PAasmOutput;
|
||||
LabelInfo: TLabelInfo;
|
||||
|
||||
{ How many instructions are between the current instruction and the last one }
|
||||
{ that modified the register }
|
||||
NrOfInstrSinceLastMod: TInstrSinceLastMod;
|
||||
|
||||
Procedure BuildLabelTableAndFixRegAlloc;
|
||||
Function FindLoHiLabels(BlockStart: Pai): Pai;
|
||||
|
||||
End;
|
||||
|
||||
Implementation
|
||||
|
||||
uses aoptmsc
|
||||
{$ifdef i386}
|
||||
, ao386msc
|
||||
{$endif i386}
|
||||
;
|
||||
|
||||
Constructor TAsmDFA.Init(_AsmL: PaasmOutPut; _Blockstart: Pai;
|
||||
Var _BlockEnd: Pai);
|
||||
Begin
|
||||
AsmL := _AsmL;
|
||||
LabelInfo.Lowabel := High(AWord);
|
||||
BlockStart := _BlockStart;
|
||||
{ initializes BlockEnd and through the methodcall also the labeltable, }
|
||||
{ lolab, hilab and labeldif. Also, the regalloc info gets corrected. }
|
||||
BlockEnd := FindLoHiLabels;
|
||||
BuildLabelTableAndFixRegAlloc;
|
||||
End;
|
||||
|
||||
Function TAsmDFA.GetLabelInfo: TLabelInfo;
|
||||
Begin
|
||||
GetLabelInfo := LabelInfo;
|
||||
End;
|
||||
|
||||
Function TAsmDFA.FindLoHiLabels: Pai;
|
||||
{ Walks through the paasmlist to find the lowest and highest label number. }
|
||||
{ Returns the last Pai object of the current block }
|
||||
Var LabelFound: Boolean;
|
||||
P: Pai;
|
||||
Begin
|
||||
LabelFound := False;
|
||||
P := BlockStart;
|
||||
While Assigned(P) And
|
||||
((P^.typ <> Ait_Marker) Or
|
||||
(Pai_Marker(P)^.Kind <> AsmBlockStart)) Do
|
||||
Begin
|
||||
If (Pai(p)^.typ = ait_label) Then
|
||||
If (Pai_Label(p)^.l^.is_used)
|
||||
Then
|
||||
Begin
|
||||
LabelFound := True;
|
||||
If (Pai_Label(p)^.l^.labelnr < LowLabel) Then
|
||||
LowLabel := Pai_Label(p)^.l^.labelnr;
|
||||
If (Pai_Label(p)^.l^.labelnr > HighLabel) Then
|
||||
HighLabel := Pai_Label(p)^.l^.labelnr;
|
||||
End;
|
||||
GetNextInstruction(p, p);
|
||||
End;
|
||||
FindLoHiLabels := p;
|
||||
If LabelFound
|
||||
Then LabelDif := HighLabel-LowLabel+1
|
||||
Else LabelDif := 0;
|
||||
End;
|
||||
|
||||
Procedure TAsmDFA.BuildLabelTableAndFixRegAlloc;
|
||||
{ Builds a table with the locations of the labels in the paasmoutput. }
|
||||
{ Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
|
||||
Var p, hp1, hp2: Pai;
|
||||
UsedRegs: TRegSet;
|
||||
Begin
|
||||
UsedRegs := [];
|
||||
With LabelInfo Do
|
||||
If (LabelDif <> 0) Then
|
||||
Begin
|
||||
GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
|
||||
FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
|
||||
p := BlockStart;
|
||||
While (P <> BlockEnd) Do
|
||||
Begin
|
||||
Case p^.typ Of
|
||||
ait_Label:
|
||||
If Pai_Label(p)^.l^.is_used Then
|
||||
LabelTable^[Pai_Label(p)^.l^.labelnr-LowLabel].PaiObj := p;
|
||||
ait_regAlloc:
|
||||
begin
|
||||
if PairegAlloc(p)^.Allocation then
|
||||
Begin
|
||||
If Not(PaiRegAlloc(p)^.Reg in UsedRegs) Then
|
||||
UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg]
|
||||
Else
|
||||
Begin
|
||||
hp1 := p;
|
||||
hp2 := nil;
|
||||
While GetLastInstruction(hp1, hp1) And
|
||||
Not(RegInInstruction(PaiRegAlloc(p)^.Reg, hp1)) Do
|
||||
hp2 := hp1;
|
||||
If hp2 <> nil Then
|
||||
Begin
|
||||
hp1 := New(PaiRegAlloc, DeAlloc(PaiRegAlloc(p)^.Reg));
|
||||
InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp1);
|
||||
End;
|
||||
End;
|
||||
End
|
||||
else
|
||||
Begin
|
||||
UsedRegs := UsedRegs - [PaiRegAlloc(p)^.Reg];
|
||||
hp1 := p;
|
||||
hp2 := nil;
|
||||
While Not(FindRegAlloc(PaiRegAlloc(p)^.Reg, Pai(hp1^.Next))) And
|
||||
GetNextInstruction(hp1, hp1) And
|
||||
RegInInstruction(PaiRegAlloc(p)^.Reg, hp1) Do
|
||||
hp2 := hp1;
|
||||
If hp2 <> nil Then
|
||||
Begin
|
||||
hp1 := Pai(p^.previous);
|
||||
AsmL^.Remove(p);
|
||||
InsertLLItem(AsmL, hp2, Pai(hp2^.Next), p);
|
||||
p := hp1;
|
||||
End;
|
||||
End;
|
||||
end;
|
||||
End;
|
||||
P := Pai(p^.Next);
|
||||
While Assigned(p) And
|
||||
(p^.typ in (SkipInstr - [ait_regalloc])) Do
|
||||
P := Pai(P^.Next);
|
||||
End;
|
||||
End;
|
||||
|
||||
Destructor TAsmDFA.Done;
|
||||
Begin
|
||||
If Assigned(LabelInfo.LabelTable) Then Dispose(LabelInfo.LabelTable);
|
||||
End;
|
||||
|
||||
Procedure TAsmOptimizer.DoDFAPass2;
|
||||
{ Analyzes the Data Flow of an assembler list. Analyses the reg contents }
|
||||
{ for the instructions between blockstart and blockend. Returns the last pai }
|
||||
{ which has been processed }
|
||||
Var
|
||||
CurProp: PPaiProp;
|
||||
Cnt, InstrCnt : Longint;
|
||||
InstrProp: TAsmInstrucProp;
|
||||
UsedRegs: TRegSet;
|
||||
p, hp, NewBlockStart : Pai;
|
||||
TmpRef: TReference;
|
||||
TmpReg: TRegister;
|
||||
{$ifdef AnalyzeLoops}
|
||||
TmpState: Byte;
|
||||
{$endif AnalyzeLoops}
|
||||
Begin
|
||||
p := BlockStart;
|
||||
UsedRegs.init;
|
||||
UsedRegs.Update(p);
|
||||
NewBlockStart := SkipHead(p);
|
||||
InstrCnt := 1;
|
||||
{ done implicitely by the constructor
|
||||
FillChar(NrOfInstrSinceLastMod, SizeOf(NrOfInstrSinceLastMod), 0); }
|
||||
While (P <> BlockEnd) Do
|
||||
Begin
|
||||
CurProp := New(PPaiProp, init);
|
||||
If (p <> NewBlockStart)
|
||||
Then
|
||||
Begin
|
||||
{$ifdef JumpAnal}
|
||||
If (p^.Typ <> ait_label) Then
|
||||
{$endif JumpAnal}
|
||||
Begin
|
||||
GetLastInstruction(p, hp);
|
||||
CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
|
||||
CurProp^.CondRegs.Flags :=
|
||||
PPaiProp(hp^.OptInfo)^.CondRegs.Flags;
|
||||
End
|
||||
End;
|
||||
CurProp^.UsedRegs.InitWithValue(UsedRegs.GetUsedRegs);
|
||||
{ CurProp^.CanBeRemoved := False;}
|
||||
UsedRegs.Update(Pai(p^.Next)));
|
||||
PPaiProp(p^.OptInfo) := CurProp;
|
||||
For TmpReg := R_EAX To R_EDI Do
|
||||
Inc(NrOfInstrSinceLastMod[TmpReg]);
|
||||
Case p^.typ Of
|
||||
ait_label:
|
||||
{$Ifndef JumpAnal}
|
||||
If (Pai_label(p)^.l^.is_used) Then
|
||||
CurProp^.DestroyAllRegs;
|
||||
{$Else JumpAnal}
|
||||
Begin
|
||||
If (Pai_Label(p)^.is_used) Then
|
||||
With LTable^[Pai_Label(p)^.l^.labelnr-LoLab] Do
|
||||
{$IfDef AnalyzeLoops}
|
||||
If (RefsFound = Pai_Label(p)^.l^.RefCount)
|
||||
{$Else AnalyzeLoops}
|
||||
If (JmpsProcessed = Pai_Label(p)^.l^.RefCount)
|
||||
{$EndIf AnalyzeLoops}
|
||||
Then
|
||||
{all jumps to this label have been found}
|
||||
{$IfDef AnalyzeLoops}
|
||||
If (JmpsProcessed > 0)
|
||||
Then
|
||||
{$EndIf AnalyzeLoops}
|
||||
{we've processed at least one jump to this label}
|
||||
Begin
|
||||
If (GetLastInstruction(p, hp) And
|
||||
Not(((hp^.typ = ait_instruction)) And
|
||||
(pai386_labeled(hp)^.is_jmp))
|
||||
Then
|
||||
{previous instruction not a JMP -> the contents of the registers after the
|
||||
previous intruction has been executed have to be taken into account as well}
|
||||
For TmpReg := R_EAX to R_EDI Do
|
||||
Begin
|
||||
If (CurProp^.Regs[TmpReg].WState <>
|
||||
PPaiProp(hp^.OptInfo)^.Regs[TmpReg].WState)
|
||||
Then DestroyReg(CurProp, TmpReg)
|
||||
End
|
||||
End
|
||||
{$IfDef AnalyzeLoops}
|
||||
Else
|
||||
{a label from a backward jump (e.g. a loop), no jump to this label has
|
||||
already been processed}
|
||||
If GetLastInstruction(p, hp) And
|
||||
Not(hp^.typ = ait_instruction) And
|
||||
(pai386_labeled(hp)^.opcode = A_JMP))
|
||||
Then
|
||||
{previous instruction not a jmp, so keep all the registers' contents from the
|
||||
previous instruction}
|
||||
Begin
|
||||
CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
|
||||
CurProp^.DirFlag := PPaiProp(hp^.OptInfo)^.DirFlag;
|
||||
End
|
||||
Else
|
||||
{previous instruction a jmp and no jump to this label processed yet}
|
||||
Begin
|
||||
hp := p;
|
||||
Cnt := InstrCnt;
|
||||
{continue until we find a jump to the label or a label which has already
|
||||
been processed}
|
||||
While GetNextInstruction(hp, hp) And
|
||||
Not((hp^.typ = ait_instruction) And
|
||||
(pai386(hp)^.is_jmp) and
|
||||
(pasmlabel(pai386(hp)^.oper[0].sym)^.labelnr = Pai_Label(p)^.l^.labelnr)) And
|
||||
Not((hp^.typ = ait_label) And
|
||||
(LTable^[Pai_Label(hp)^.l^.labelnr-LoLab].RefsFound
|
||||
= Pai_Label(hp)^.l^.RefCount) And
|
||||
(LTable^[Pai_Label(hp)^.l^.labelnr-LoLab].JmpsProcessed > 0)) Do
|
||||
Inc(Cnt);
|
||||
If (hp^.typ = ait_label)
|
||||
Then
|
||||
{there's a processed label after the current one}
|
||||
Begin
|
||||
CurProp^.Regs := PaiPropBlock^[Cnt].Regs;
|
||||
CurProp^.DirFlag := PaiPropBlock^[Cnt].DirFlag;
|
||||
End
|
||||
Else
|
||||
{there's no label anymore after the current one, or they haven't been
|
||||
processed yet}
|
||||
Begin
|
||||
GetLastInstruction(p, hp);
|
||||
CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
|
||||
CurProp^.DirFlag := PPaiProp(hp^.OptInfo)^.DirFlag;
|
||||
DestroyAllRegs(PPaiProp(hp^.OptInfo))
|
||||
End
|
||||
End
|
||||
{$EndIf AnalyzeLoops}
|
||||
Else
|
||||
{not all references to this label have been found, so destroy all registers}
|
||||
Begin
|
||||
GetLastInstruction(p, hp);
|
||||
CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
|
||||
CurProp^.DirFlag := PPaiProp(hp^.OptInfo)^.DirFlag;
|
||||
DestroyAllRegs(CurProp)
|
||||
End;
|
||||
End;
|
||||
{$EndIf JumpAnal}
|
||||
|
||||
{$ifdef GDB}
|
||||
ait_stabs, ait_stabn, ait_stab_function_name:;
|
||||
{$endif GDB}
|
||||
|
||||
ait_instruction:
|
||||
Begin
|
||||
if pai386(p)^.is_jmp then
|
||||
begin
|
||||
{$IfNDef JumpAnal}
|
||||
;
|
||||
{$Else JumpAnal}
|
||||
With LTable^[pasmlabel(pai386(p)^.oper[0].sym)^.labelnr-LoLab] Do
|
||||
If (RefsFound = pasmlabel(pai386(p)^.oper[0].sym)^.RefCount) Then
|
||||
Begin
|
||||
If (InstrCnt < InstrNr)
|
||||
Then
|
||||
{forward jump}
|
||||
If (JmpsProcessed = 0) Then
|
||||
{no jump to this label has been processed yet}
|
||||
Begin
|
||||
PaiPropBlock^[InstrNr].Regs := CurProp^.Regs;
|
||||
PaiPropBlock^[InstrNr].DirFlag := CurProp^.DirFlag;
|
||||
Inc(JmpsProcessed);
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
For TmpReg := R_EAX to R_EDI Do
|
||||
If (PaiPropBlock^[InstrNr].Regs[TmpReg].WState <>
|
||||
CurProp^.Regs[TmpReg].WState) Then
|
||||
DestroyReg(@PaiPropBlock^[InstrNr], TmpReg);
|
||||
Inc(JmpsProcessed);
|
||||
End
|
||||
{$ifdef AnalyzeLoops}
|
||||
Else
|
||||
{ backward jump, a loop for example}
|
||||
{ If (JmpsProcessed > 0) Or
|
||||
Not(GetLastInstruction(PaiObj, hp) And
|
||||
(hp^.typ = ait_labeled_instruction) And
|
||||
(pai386_labeled(hp)^.opcode = A_JMP))
|
||||
Then}
|
||||
{instruction prior to label is not a jmp, or at least one jump to the label
|
||||
has yet been processed}
|
||||
Begin
|
||||
Inc(JmpsProcessed);
|
||||
For TmpReg := R_EAX to R_EDI Do
|
||||
If (PaiPropBlock^[InstrNr].Regs[TmpReg].WState <>
|
||||
CurProp^.Regs[TmpReg].WState)
|
||||
Then
|
||||
Begin
|
||||
TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
|
||||
Cnt := InstrNr;
|
||||
While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
|
||||
Begin
|
||||
DestroyReg(@PaiPropBlock^[Cnt], TmpReg);
|
||||
Inc(Cnt);
|
||||
End;
|
||||
While (Cnt <= InstrCnt) Do
|
||||
Begin
|
||||
Inc(PaiPropBlock^[Cnt].Regs[TmpReg].WState);
|
||||
Inc(Cnt)
|
||||
End
|
||||
End;
|
||||
End
|
||||
{ Else }
|
||||
{instruction prior to label is a jmp and no jumps to the label have yet been
|
||||
processed}
|
||||
{ Begin
|
||||
Inc(JmpsProcessed);
|
||||
For TmpReg := R_EAX to R_EDI Do
|
||||
Begin
|
||||
TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
|
||||
Cnt := InstrNr;
|
||||
While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
|
||||
Begin
|
||||
PaiPropBlock^[Cnt].Regs[TmpReg] := CurProp^.Regs[TmpReg];
|
||||
Inc(Cnt);
|
||||
End;
|
||||
TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
|
||||
While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
|
||||
Begin
|
||||
DestroyReg(@PaiPropBlock^[Cnt], TmpReg);
|
||||
Inc(Cnt);
|
||||
End;
|
||||
While (Cnt <= InstrCnt) Do
|
||||
Begin
|
||||
Inc(PaiPropBlock^[Cnt].Regs[TmpReg].WState);
|
||||
Inc(Cnt)
|
||||
End
|
||||
End
|
||||
End}
|
||||
{$endif AnalyzeLoops}
|
||||
End;
|
||||
{$EndIf JumpAnal}
|
||||
end
|
||||
else
|
||||
begin
|
||||
InstrProp := AsmInstr[PInstr(p)^.opcode];
|
||||
If IsStoreInstr(p) Then
|
||||
Begin
|
||||
CurProp^.ReadReg(PInstr(p)^.oper[StoreSrc].reg);
|
||||
CurProp^.ReadRef(PInstr(p)^.oper[StoreDst].ref);
|
||||
CurProp^.DestroyRefs(PInstr(p)^.oper[StoreDst].ref^,
|
||||
PInstr(p)^.oper[StoreSrc].reg);
|
||||
End
|
||||
Else If IsLoadInstr(p) Then
|
||||
Begin
|
||||
CurProp^.ReadRef(PInstr(p)^.oper[LoadSrc].ref);
|
||||
CurProp^.ReadReg(PInstr(p)^.oper[LoadDst].reg);
|
||||
TmpReg := RegMaxSize(PInstr(p)^.oper[1].reg);
|
||||
If RegInRef(TmpReg, Pai386(p)^.oper[0].ref^) And
|
||||
(CurProp^.Regs[TmpReg].Typ = Con_Ref)
|
||||
Then
|
||||
Begin
|
||||
With CurProp^.Regs[TmpReg] Do
|
||||
Begin
|
||||
IncState(WState);
|
||||
{also store how many instructions are part of the sequence in the first
|
||||
instructions PPaiProp, so it can be easily accessed from within
|
||||
CheckSequence}
|
||||
Inc(NrOfMods, NrOfInstrSinceLastMod[TmpReg]);
|
||||
PPaiProp(Pai(StartMod)^.OptInfo)^.Regs[TmpReg].NrOfMods := NrOfMods;
|
||||
NrOfInstrSinceLastMod[TmpReg] := 0;
|
||||
End;
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
DestroyReg(CurProp, TmpReg);
|
||||
If Not(RegInRef(TmpReg, Pai386(p)^.oper[0].ref^)) Then
|
||||
With CurProp^.Regs[TmpReg] Do
|
||||
Begin
|
||||
Typ := Con_Ref;
|
||||
StartMod := p;
|
||||
NrOfMods := 1;
|
||||
End
|
||||
End;
|
||||
{$ifdef StateDebug}
|
||||
hp := new(pai_asm_comment,init(strpnew(att_reg2str[TmpReg]+': '+tostr(CurProp^.Regs[TmpReg].WState))));
|
||||
InsertLLItem(AsmL, p, p^.next, hp);
|
||||
{$endif StateDebug}
|
||||
|
||||
End;
|
||||
Top_Const:
|
||||
Begin
|
||||
Case Pai386(p)^.oper[1].typ Of
|
||||
Top_Reg:
|
||||
Begin
|
||||
TmpReg := Reg32(Pai386(p)^.oper[1].reg);
|
||||
With CurProp^.Regs[TmpReg] Do
|
||||
Begin
|
||||
DestroyReg(CurProp, TmpReg);
|
||||
typ := Con_Const;
|
||||
StartMod := p;
|
||||
End
|
||||
End;
|
||||
Top_Ref:
|
||||
Begin
|
||||
ReadRef(CurProp, Pai386(p)^.oper[1].ref);
|
||||
DestroyRefs(P, Pai386(p)^.oper[1].ref^, R_NO);
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
A_IMUL:
|
||||
Begin
|
||||
ReadOp(CurProp, Pai386(p)^.oper[0]);
|
||||
ReadOp(CurProp, Pai386(p)^.oper[1]);
|
||||
If (Pai386(p)^.oper[2].typ = top_none) Then
|
||||
If (Pai386(p)^.oper[1].typ = top_none) Then
|
||||
Begin
|
||||
DestroyReg(CurProp, R_EAX);
|
||||
DestroyReg(CurProp, R_EDX)
|
||||
End
|
||||
Else
|
||||
{$ifdef arithopt}
|
||||
AddInstr2OpContents(Pai386(p), Pai386(p)^.oper[1])
|
||||
{$else arithopt}
|
||||
DestroyOp(p, Pai386(p)^.oper[1])
|
||||
{$endif arithopt}
|
||||
Else
|
||||
{$ifdef arithopt}
|
||||
AddInstr2OpContents(Pai386(p), Pai386(p)^.oper[2]);
|
||||
{$else arithopt}
|
||||
DestroyOp(p, Pai386(p)^.oper[2]);
|
||||
{$endif arithopt}
|
||||
End;
|
||||
A_XOR:
|
||||
Begin
|
||||
ReadOp(CurProp, Pai386(p)^.oper[0]);
|
||||
ReadOp(CurProp, Pai386(p)^.oper[1]);
|
||||
If (Pai386(p)^.oper[0].typ = top_reg) And
|
||||
(Pai386(p)^.oper[1].typ = top_reg) And
|
||||
(Pai386(p)^.oper[0].reg = Pai386(p)^.oper[1].reg)
|
||||
Then
|
||||
Begin
|
||||
DestroyReg(CurProp, Pai386(p)^.oper[0].reg);
|
||||
CurProp^.Regs[Reg32(Pai386(p)^.oper[0].reg)].typ := Con_Const;
|
||||
CurProp^.Regs[Reg32(Pai386(p)^.oper[0].reg)].StartMod := Pointer(0)
|
||||
End
|
||||
Else
|
||||
DestroyOp(p, Pai386(p)^.oper[1]);
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
Cnt := 1;
|
||||
While (Cnt <= MaxCh) And
|
||||
(InstrProp.Ch[Cnt] <> C_None) Do
|
||||
Begin
|
||||
Case InstrProp.Ch[Cnt] Of
|
||||
C_REAX..C_REDI: ReadReg(CurProp,TCh2Reg(InstrProp.Ch[Cnt]));
|
||||
C_WEAX..C_RWEDI:
|
||||
Begin
|
||||
If (InstrProp.Ch[Cnt] >= C_RWEAX) Then
|
||||
ReadReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]));
|
||||
DestroyReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]));
|
||||
End;
|
||||
{$ifdef arithopt}
|
||||
C_MEAX..C_MEDI:
|
||||
AddInstr2RegContents({$ifdef statedebug} asml, {$endif}
|
||||
Pai386(p),
|
||||
TCh2Reg(InstrProp.Ch[Cnt]));
|
||||
{$endif arithopt}
|
||||
C_CDirFlag: CurProp^.DirFlag := F_NotSet;
|
||||
C_SDirFlag: CurProp^.DirFlag := F_Set;
|
||||
C_Rop1: ReadOp(CurProp, Pai386(p)^.oper[0]);
|
||||
C_Rop2: ReadOp(CurProp, Pai386(p)^.oper[1]);
|
||||
C_ROp3: ReadOp(CurProp, Pai386(p)^.oper[2]);
|
||||
C_Wop1..C_RWop1:
|
||||
Begin
|
||||
If (InstrProp.Ch[Cnt] in [C_RWop1]) Then
|
||||
ReadOp(CurProp, Pai386(p)^.oper[0]);
|
||||
DestroyOp(p, Pai386(p)^.oper[0]);
|
||||
End;
|
||||
{$ifdef arithopt}
|
||||
C_Mop1:
|
||||
AddInstr2OpContents({$ifdef statedebug} asml, {$endif}
|
||||
Pai386(p), Pai386(p)^.oper[0]);
|
||||
{$endif arithopt}
|
||||
C_Wop2..C_RWop2:
|
||||
Begin
|
||||
If (InstrProp.Ch[Cnt] = C_RWop2) Then
|
||||
ReadOp(CurProp, Pai386(p)^.oper[1]);
|
||||
DestroyOp(p, Pai386(p)^.oper[1]);
|
||||
End;
|
||||
{$ifdef arithopt}
|
||||
C_Mop2:
|
||||
AddInstr2OpContents({$ifdef statedebug} asml, {$endif}
|
||||
Pai386(p), Pai386(p)^.oper[1]);
|
||||
{$endif arithopt}
|
||||
C_WOp3..C_RWOp3:
|
||||
Begin
|
||||
If (InstrProp.Ch[Cnt] = C_RWOp3) Then
|
||||
ReadOp(CurProp, Pai386(p)^.oper[2]);
|
||||
DestroyOp(p, Pai386(p)^.oper[2]);
|
||||
End;
|
||||
{$ifdef arithopt}
|
||||
C_Mop3:
|
||||
AddInstr2OpContents({$ifdef statedebug} asml, {$endif}
|
||||
Pai386(p), Pai386(p)^.oper[2]);
|
||||
{$endif arithopt}
|
||||
C_WMemEDI:
|
||||
Begin
|
||||
ReadReg(CurProp, R_EDI);
|
||||
FillChar(TmpRef, SizeOf(TmpRef), 0);
|
||||
TmpRef.Base := R_EDI;
|
||||
DestroyRefs(p, TmpRef, R_NO)
|
||||
End;
|
||||
C_RFlags, C_WFlags, C_RWFlags, C_FPU:
|
||||
Else
|
||||
Begin
|
||||
DestroyAllRegs(CurProp);
|
||||
End;
|
||||
End;
|
||||
Inc(Cnt);
|
||||
End
|
||||
End;
|
||||
end;
|
||||
End;
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
DestroyAllRegs(CurProp);
|
||||
End;
|
||||
End;
|
||||
Inc(InstrCnt);
|
||||
GetNextInstruction(p, p);
|
||||
End;
|
||||
End;
|
||||
|
||||
|
||||
End.
|
Loading…
Reference in New Issue
Block a user