|
@@ -1,1375 +0,0 @@
|
|
|
-{
|
|
|
- $Id$
|
|
|
- Copyright (c) 1993-98 by Florian Klaempfl and Jonas Maebe
|
|
|
-
|
|
|
- This include file contains the reloading optimizer for i386+
|
|
|
-
|
|
|
- This program is free software; you can redistribute it and/or modify
|
|
|
- it under the terms of the GNU General Public License as published by
|
|
|
- the Free Software Foundation; either version 2 of the License, or
|
|
|
- (at your option) any later version.
|
|
|
-
|
|
|
- This program is distributed in the hope that it will be useful,
|
|
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
- GNU General Public License for more details.
|
|
|
-
|
|
|
- You should have received a copy of the GNU General Public License
|
|
|
- along with this program; if not, write to the Free Software
|
|
|
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
-
|
|
|
- ****************************************************************************
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-{$Define OptimizeMovs}
|
|
|
-
|
|
|
-Procedure ReloadOpt(AsmL: PaasmOutput);
|
|
|
-
|
|
|
-Const MaxCh = 3;
|
|
|
-
|
|
|
- {content types}
|
|
|
- con_Unknown = 0;
|
|
|
- con_ref = 1;
|
|
|
- con_const = 2;
|
|
|
- con_symbol = 3;
|
|
|
-
|
|
|
-Type TChange = (C_None,
|
|
|
- C_EAX, C_ECX, C_EDX, C_EBX, C_ESP, C_EBP, C_ESI, C_EDI,
|
|
|
- C_CDirFlag, C_SDirFlag, C_Flags, C_FPU,
|
|
|
- C_Op1, C_Op2, C_Op3,
|
|
|
- C_MemEDI);
|
|
|
-
|
|
|
- TFlagContents = (F_Unknown, F_NotSet, F_Set);
|
|
|
-
|
|
|
- TAsmInstrucProp = Record
|
|
|
- NCh: Byte;
|
|
|
- Ch: Array[1..MaxCh] of TChange;
|
|
|
- End;
|
|
|
-
|
|
|
- TContent = Record
|
|
|
- StartMod: Pointer; {start and end of block instructions that defines the
|
|
|
- content of this register; If Typ = con_const, then
|
|
|
- Longint(StartMod) = value of the constant)}
|
|
|
- State: Word; {starts at 0, gets increased everytime the register is modified}
|
|
|
- NrOfMods: Byte;
|
|
|
-{ ModReg: TRegister; }{if one register gets a block assigned from an other register,
|
|
|
- this variable holds the name of that register (so it can be
|
|
|
- substituted when checking the block afterwards)}
|
|
|
- Typ: Byte; {con_*}
|
|
|
-{ CanBeDestroyed: Boolean;} {if it's a register modified by the optimizer}
|
|
|
- End;
|
|
|
-
|
|
|
- TRegContent = Array[R_NO..R_EDI] Of TContent;
|
|
|
- TRegFPUContent = Array[R_ST..R_ST7] Of TContent;
|
|
|
-
|
|
|
- TPaiProp = Record
|
|
|
- Regs: TRegContent;
|
|
|
-{ FPURegs: TRegFPUContent;} {currently not yet used}
|
|
|
- LineSave: Longint;
|
|
|
- DirFlag: TFlagContents;
|
|
|
- {can this instruction be removed?}
|
|
|
- CanBeRemoved: Boolean;
|
|
|
- End;
|
|
|
-
|
|
|
- PPaiProp = ^TPaiProp;
|
|
|
-{$IfDef TP}
|
|
|
- TPaiPropBlock = Array[1..(65520 div (((SizeOf(TPaiProp)+1)div 2)*2))] Of TPaiProp;
|
|
|
-{$else}
|
|
|
- TPaiPropBlock = Array[1..250000] Of TPaiProp;
|
|
|
-{$EndIf TP}
|
|
|
- PPaiPropBlock = ^TPaiPropBlock;
|
|
|
-
|
|
|
-Const AsmInstr: Array[tasmop] Of TAsmInstrucProp = (
|
|
|
- {MOV} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {MOVZX} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {MOVSX} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {LABEL} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
|
|
|
- {ADD} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {CALL} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
|
|
|
- {IDIV} (NCh: 3; Ch: (C_EAX, C_EDX, C_Flags)),
|
|
|
- {IMUL} (NCh: 3; Ch: (C_EAX, C_EDX, C_Flags)), {handled separately, because several forms exist}
|
|
|
- {JMP} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
|
|
|
- {LEA} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {MUL} (NCh: 3; Ch: (C_EAX, C_EDX, C_Flags)),
|
|
|
- {NEG} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {NOT} (NCh: 2; Ch: (C_Op1, C_Flags, C_None)),
|
|
|
- {POP} (NCh: 2; Ch: (C_Op1, C_ESP, C_None)),
|
|
|
- {POPAD} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
|
|
|
- {PUSH} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
|
|
|
-{PUSHAD} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
|
|
|
- {RET} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
|
|
|
- {SUB} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {XCHG} (NCh: 2; Ch: (C_Op1, C_Op2, C_None)), {(will be) handled seperately}
|
|
|
- {XOR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {FILD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {CMP} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
|
|
|
- {JZ} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {INC} (NCh: 2; Ch: (C_Op1, C_Flags, C_None)),
|
|
|
- {DEC} (NCh: 2; Ch: (C_Op1, C_Flags, C_None)),
|
|
|
- {SETE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETNE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETG} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETLE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETGE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {JE} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JNE} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JL} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JG} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JLE} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JGE} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {OR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {FLD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FADD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FMUL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FSUB} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FDIV} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FCHS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FLD1} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FIDIV} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {CLTD} (NCh: 1; Ch: (C_EDX, C_None, C_None)),
|
|
|
- {JNZ} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {FSTP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {AND} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {JNO} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {NOTH} (NCh: 0; Ch: (C_None, C_None, C_None)), {***???***}
|
|
|
- {NONE} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {ENTER} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
|
|
|
- {LEAVE} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
|
|
|
- {CLD} (NCh: 1; Ch: (C_CDirFlag, C_None, C_None)),
|
|
|
- {MOVS} (NCh: 3; Ch: (C_ESI, C_EDI, C_MemEDI)),
|
|
|
- {REP} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
|
|
|
- {SHL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {SHR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {BOUND} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JNS} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JS} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JO} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {SAR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {TEST} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
|
|
|
- {FCOM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FCOMP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FCOMPP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FXCH} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FADDP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FMULP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FSUBP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FDIVP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FNSTS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SAHF} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
|
|
|
-{FDIVRP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FSUBRP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {SETC} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETNC} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {JC} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JNC} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JA} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JAE} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JB} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JBE} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {SETA} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETAE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETB} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETBE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {AAA} (NCh: 2; Ch: (C_EAX, C_Flags, C_None)),
|
|
|
- {AAD} (NCh: 2; Ch: (C_EAX, C_Flags, C_None)),
|
|
|
- {AAM} (NCh: 2; Ch: (C_EAX, C_Flags, C_None)),
|
|
|
- {AAS} (NCh: 2; Ch: (C_EAX, C_Flags, C_None)),
|
|
|
- {CBW} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
|
|
|
- {CDQ} (NCh: 2; Ch: (C_EAX, C_EDX, C_None)),
|
|
|
- {CLC} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
|
|
|
- {CLI} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
|
|
|
- {CLTS} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {CMC} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
|
|
|
- {CWD} (NCh: 2; Ch: (C_EAX, C_EDX, C_None)),
|
|
|
- {CWDE} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
|
|
|
- {DAA} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
|
|
|
- {DAS} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
|
|
|
- {HLT} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {IRET} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
|
|
|
- {LAHF} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
|
|
|
- {LODS} (NCh: 2; Ch: (C_EAX, C_ESI, C_None)),
|
|
|
- {LOCK} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {NOP} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {PUSHA} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
|
|
|
- {PUSHF} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
|
|
|
-{PUSHFD} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
|
|
|
- {STC} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
|
|
|
- {STD} (NCh: 1; Ch: (C_SDirFlag, C_None, C_None)),
|
|
|
- {STI} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
|
|
|
- {STOS} (NCh: 2; Ch: (C_MemEDI, C_EDI, C_None)),
|
|
|
- {WAIT} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {XLAT} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
|
|
|
- {XLATB} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
|
|
|
- {MOVSB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{MOVSBL} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{MOVSBW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{MOVSWL} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {MOVZB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{MOVZWL} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {POPA} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
|
|
|
- {IN} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {OUT} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {LDS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {LCS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {LES} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {LFS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {LGS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {LSS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {POPF} (NCh: 2; Ch: (C_Flags, C_ESP, C_None)),
|
|
|
- {SBB} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {ADC} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {DIV} (NCh: 3; Ch: (C_EAX, C_EDX, C_Flags)),
|
|
|
- {ROR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {ROL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {RCL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {RCR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {SAL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {SHLD} (NCh: 2; Ch: (C_Op3, C_Flags, C_None)),
|
|
|
- {SHRD} (NCh: 2; Ch: (C_Op3, C_Flags, C_None)),
|
|
|
- {LCALL} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
|
|
|
- {LJMP} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
|
|
|
- {LRET} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
|
|
|
- {JNAE} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JNB} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JNA} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JNBE} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JP} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JNP} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JPE} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JPO} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JNGE} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JNG} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JNL} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JNLE} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JCXZ} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {JECXZ} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {LOOP} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
|
|
|
- {CMPS} (NCh: 3; Ch: (C_ESI, C_EDI, C_Flags)),
|
|
|
- {INS} (NCh: 1; Ch: (C_EDI, C_None, C_None)),
|
|
|
- {OUTS} (NCh: 1; Ch: (C_ESI, C_None, C_None)),
|
|
|
- {SCAS} (NCh: 2; Ch: (C_EDI, C_Flags, C_None)),
|
|
|
- {BSF} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {BSR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {BT} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
|
|
|
- {BTC} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {BTR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {BTS} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {INT} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
|
|
|
- {INT3} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {INTO} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
|
|
|
-{BOUNDL} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
-{BOUNDW} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {LOOPZ} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
|
|
|
- {LOOPE} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
|
|
|
-{LOOPNZ} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
|
|
|
-{LOOPNE} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
|
|
|
- {SETO} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETNO} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
-{SETNAE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETNB} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETZ} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETNZ} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETNA} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
-{SETNBE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETNS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETPE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETNP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETPO} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
-{SETNGE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETNL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SETNG} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
-{SETNLE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {ARPL} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
|
|
|
- {LAR} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
- {LGDT} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {LIDT} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {LLDT} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {LMSW} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {LSL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
|
|
|
- {LTR} (NCh: 0; Ch: (C_None, C_None, C_None)),
|
|
|
- {SGDT} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SIDT} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SLDT} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {SMSW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {STR} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {VERR} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
|
|
|
- {VERW} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
|
|
|
- {FABS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FBLD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FBSTP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {FCLEX} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FNCLEX} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FCOS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FDECSTP}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FDISI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FNDISI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FDIVR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FENI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FNENI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FFREE} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FIADD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FICOM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FICOMP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FIDIVR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FIMUL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FINCSTP}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FINIT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FNINIT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FIST} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {FISTP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {FISUB} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FSUBR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FLDCW} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FLDENV} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FLDLG2} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FLDLN2} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FLDL2E} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FLDL2T} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FLDPI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FLDS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FLDZ} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FNOP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FPATAN} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FPREM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FPREM1} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FPTAN} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FRNDINT}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FRSTOR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FSAVE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
-{FNSAVE} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FSCALE} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FSETPM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FSIN} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FSINCOS}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FSQRT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FST} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {FSTCW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
-{FNSTCW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
-{FSTENV} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
-{FNSTENV}(NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {FSTSW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
-{FNSTSW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {FTST} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FUCOM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FUCOMP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FUCOMPP}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FWAIT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FXAM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FXTRACT}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FYL2X} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FYL2XP1}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {F2XM1} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FILDQ} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FILDS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FILDL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FLDL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FLDT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FISTQ} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {FISTS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {FISTL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {FSTL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {FSTS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {FSTPS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
-{FISTPL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {FSTPL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
-{FISTPS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
-{FISTPQ} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
- {FSTPT} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
|
|
|
-{FCOMPS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FICOMPL}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FCOMPL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FICOMPS}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FCOMS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FICOML} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FCOML} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FICOMS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FIADDL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FADDL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FIADDS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FISUBL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FSUBL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FISUBS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FSUBS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FSUBR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FSUBRS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FISUBRL}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FSUBRL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FISUBRS}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FMULS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FIMUL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FMULL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FIMULS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FIDIVS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FIDIVL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {FDIVL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FIDIVS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FDIVRS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FIDIVRL}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FDIVRL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{FIDIVRS}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {REPE} (NCh: 0; Ch: (C_ECX, C_None, C_None)),
|
|
|
- {REPNE} (NCh: 0; Ch: (C_ECX, C_None, C_None)),
|
|
|
- {FADDS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
- {POPFD} (NCh: 2; Ch: (C_ESP, C_Flags, C_None)),
|
|
|
-{below are the MMX instructions}
|
|
|
-{A_EMMS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_MOVD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_MOVQ} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PACKSSDW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PACKSSWB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PACKUSWB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PADDB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PADDD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PADDSB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PADDSW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PADDUSB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PADDUSW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PADDW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PAND} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PANDN} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PCMPEQB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PCMPEQD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PCMPEQW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PCMPGTB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PCMPGTD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PCMPGTW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PMADDWD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PMULHW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PMULLW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_POR} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSLLD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSLLQ} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSLLW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSRAD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSRAW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSRLD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSRLQ} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSRLW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSUBB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSUBD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSUBSB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSUBSW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSUBUSB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSUBUSW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PSUBW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
|
|
|
-{A_PUNPCKHBW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PUNPCKHDQ} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PUNPCKHWD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PUNPCKLBW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PUNPCKLDQ} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PUNPCKLWD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
|
|
|
-{A_PXOR} (NCh: 1; Ch: (C_Op2, C_None, C_None)));
|
|
|
-
|
|
|
-Var NrOfPaiObjs, NrOfPaiFast: Longint;
|
|
|
- PaiPropBlock: PPaiPropBlock;
|
|
|
- NrOfInstrSinceLastMod: Array[R_EAX..R_EDI] Of Byte;
|
|
|
-
|
|
|
-Function TCh2Reg(Ch: TChange): TRegister;
|
|
|
-{converts a TChange variable to a TRegister}
|
|
|
-Begin
|
|
|
- If (CH <= C_EDI)
|
|
|
- Then TCh2Reg := TRegister(Byte(Ch))
|
|
|
- Else InternalError($db)
|
|
|
-End;
|
|
|
-
|
|
|
-Procedure DestroyReg(p1: pai; Reg: TRegister);
|
|
|
-{Destroys the contents of the register Reg in the PPaiProp of P}
|
|
|
-Var TmpState: Longint;
|
|
|
-Begin
|
|
|
- Reg := Reg32(Reg);
|
|
|
- NrOfInstrSinceLastMod[Reg] := 0;
|
|
|
- If (Reg >= R_EAX) And (Reg <= R_EDI)
|
|
|
- Then
|
|
|
- Begin
|
|
|
- TmpState := PPaiProp(p1^.fileinfo.line)^.Regs[Reg].State+1;
|
|
|
- FillChar(PPaiProp(p1^.fileinfo.line)^.Regs[Reg], SizeOf(TContent), 0);
|
|
|
- PPaiProp(p1^.fileinfo.line)^.Regs[Reg].State := TmpState;
|
|
|
- End;
|
|
|
-End;
|
|
|
-
|
|
|
-(*Function FindZeroreg(p: Pai; Var Result: TRegister): Boolean;
|
|
|
-{Finds a register which contains the constant zero}
|
|
|
-Var Counter: TRegister;
|
|
|
-Begin
|
|
|
- Counter := R_EAX;
|
|
|
- FindZeroReg := True;
|
|
|
- While (Counter <= R_EDI) And
|
|
|
- ((PPaiProp(p^.fileinfo.line)^.Regs[Counter].Typ <> Con_Const) or
|
|
|
- (PPaiProp(p^.fileinfo.line)^.Regs[Counter].StartMod <> Pointer(0))) Do
|
|
|
- Inc(Byte(Counter));
|
|
|
- If (PPaiProp(p^.fileinfo.line)^.Regs[Counter].Typ = Con_Const) And
|
|
|
- (PPaiProp(p^.fileinfo.line)^.Regs[Counter].StartMod = Pointer(0))
|
|
|
- Then Result := Counter
|
|
|
- Else FindZeroReg := False;
|
|
|
-End;*)
|
|
|
-
|
|
|
-Procedure DestroyRefs(p: pai; Const Ref: TReference; WhichRegNot: TRegister);
|
|
|
-{destroys all registers which possibly contain a reference to Ref}
|
|
|
-Var Counter: TRegister;
|
|
|
-Begin
|
|
|
-WhichRegNot := Reg32(WhichRegNot);
|
|
|
-If (Ref.base <> R_NO) Or
|
|
|
- (Ref.index <> R_NO)
|
|
|
- Then
|
|
|
- Begin
|
|
|
- If (Ref.base = ProcInfo.FramePointer)
|
|
|
- Then
|
|
|
-{write something to a parameter or a local variable}
|
|
|
- For Counter := R_EAX to R_EDI Do
|
|
|
- With PPaiProp(p^.fileinfo.line)^.Regs[Counter] Do
|
|
|
- Begin
|
|
|
- If (Counter <> WhichRegNot) And
|
|
|
- (typ = Con_Ref) And
|
|
|
- (Pai(StartMod)^.typ = ait_instruction) And
|
|
|
- (Pai386(StartMod)^.op1t = top_ref) And
|
|
|
- (RefsEqual(TReference(Pai386(StartMod)^.op1^), Ref) Or
|
|
|
- (Not(cs_UncertainOpts in AktSwitches) And
|
|
|
- (NrOfMods <> 1)))
|
|
|
- Then DestroyReg(p, Counter)
|
|
|
- End
|
|
|
- Else
|
|
|
- {writing something to a pointer location}
|
|
|
- For Counter := R_EAX to R_EDI Do
|
|
|
- With PPaiProp(p^.fileinfo.line)^.Regs[Counter] Do
|
|
|
- If (Counter <> WhichRegNot) And
|
|
|
- (typ = Con_Ref) And
|
|
|
- (Not(cs_UncertainOpts in AktSwitches) Or
|
|
|
- (Ref.Base = R_EDI) Or
|
|
|
- (Not((NrOfMods = 1) And
|
|
|
- (Pai(StartMod)^.typ = ait_instruction) And
|
|
|
- (Pai386(StartMod)^.op1t = top_ref) And
|
|
|
- (PReference(Pai386(StartMod)^.op1)^.base = ProcInfo.FramePointer))))
|
|
|
- Then
|
|
|
- DestroyReg(p, Counter) {we don't know what memory location the reference points to,
|
|
|
- so we just destroy every register which contains a memory
|
|
|
- reference}
|
|
|
- End
|
|
|
- Else {the ref is a var name or we just have a reference an absolute offset}
|
|
|
- Begin
|
|
|
- For Counter := R_EAX to R_EDI Do
|
|
|
- If (Counter <> WhichRegNot) And
|
|
|
- (PPaiProp(p^.fileinfo.line)^.Regs[Counter].typ = Con_Ref) And
|
|
|
- (Not(cs_UncertainOpts in AktSwitches) Or
|
|
|
- RefsEqual(Ref,
|
|
|
- TReference(Pai386(PPaiProp(p^.fileinfo.line)^.Regs[Counter].StartMod)^.op1^))) Then
|
|
|
- DestroyReg(p, Counter)
|
|
|
- End;
|
|
|
-End;
|
|
|
-
|
|
|
-{$IfDef OptimizeMovs}
|
|
|
-
|
|
|
-Function OpsEqual(typ: Longint; op1, op2: Pointer): Boolean;
|
|
|
-Begin {checks whether the two ops are equal}
|
|
|
- Case typ Of
|
|
|
- Top_Reg, Top_Const: OpsEqual := op1 = op2;
|
|
|
- Top_Ref: OpsEqual := RefsEqual(TReference(op1^), TReference(op2^));
|
|
|
- Top_None: OpsEqual := True
|
|
|
- Else OpsEqual := False
|
|
|
- End;
|
|
|
-End;
|
|
|
-
|
|
|
-Function RegsSameContent(p1, p2: Pai; Reg: TRegister): Boolean;
|
|
|
-{checks whether Reg has the same content in the PPaiProp of p1 and p2}
|
|
|
-Begin
|
|
|
- Reg := Reg32(Reg);
|
|
|
- RegsSameContent :=
|
|
|
- PPaiProp(p1^.fileinfo.line)^.Regs[Reg].State =
|
|
|
- PPaiProp(p2^.fileinfo.line)^.Regs[Reg].State;
|
|
|
-End;
|
|
|
-
|
|
|
-Function InstructionsEqual(p1, p2: Pai): Boolean;
|
|
|
-Begin {checks whether two Pai386 instructions are equal}
|
|
|
- InstructionsEqual :=
|
|
|
- Assigned(p1) And Assigned(p2) And
|
|
|
-{$ifdef regalloc}
|
|
|
- ((((Pai(p1)^.typ = ait_regalloc) And
|
|
|
- (Pai(p2)^.typ = ait_regalloc)) Or
|
|
|
- ((Pai(p1)^.typ = ait_regdealloc) And
|
|
|
- (Pai(p2)^.typ = ait_regdealloc))) And
|
|
|
- (PaiRegAlloc(p1)^.reg = PaiRegAlloc(p2)^.reg)) Or
|
|
|
-{$endif regalloc}
|
|
|
- ((Pai(p1)^.typ = ait_instruction) And
|
|
|
- (Pai(p1)^.typ = ait_instruction) And
|
|
|
- (Pai386(p1)^._operator = Pai386(p2)^._operator) And
|
|
|
- (Pai386(p1)^.op1t = Pai386(p2)^.op1t) And
|
|
|
- (Pai386(p1)^.op2t = Pai386(p2)^.op2t) And
|
|
|
- OpsEqual(Pai386(p1)^.op1t, Pai386(p1)^.op1, Pai386(p2)^.op1) And
|
|
|
- OpsEqual(Pai386(p1)^.op2t, Pai386(p1)^.op2, Pai386(p2)^.op2))
|
|
|
-End;
|
|
|
-
|
|
|
-Function CheckSequence(p: Pai; Reg: TRegister; Var Found: Longint): Boolean;
|
|
|
-{checks whether the current instruction sequence (starting with p) and the
|
|
|
- one between StartMod and EndMod of Reg are the same. If so, the number of
|
|
|
- instructions that match is stored in Found and true is returned, otherwise
|
|
|
- Found holds the number of instructions between StartMod and EndMod and false
|
|
|
- is returned}
|
|
|
-Var hp2, hp3, EndMod: Pai;
|
|
|
- TmpResult: Boolean;
|
|
|
- RegsNotYetChecked: Set Of TRegister;
|
|
|
- Counter: Byte;
|
|
|
-
|
|
|
-Function NoChangedRegInRef(oldp, newp: Pai): Boolean;
|
|
|
-Var TmpP: Pai;
|
|
|
-{checks if the first operator of newp is a reference and in that case checks
|
|
|
- whether that reference includes regs that have been changed since oldp. This
|
|
|
- to avoid wrong optimizations like
|
|
|
-
|
|
|
- movl 8(%epb), %eax movl 8(%epb), %eax
|
|
|
- movl 12(%epb), %edx movl 12(%epb), %edx
|
|
|
- movl (%eax,%edx,1), %edi movl (%eax,%edx,1), %edi
|
|
|
- pushl %edi being converted to pushl %edi
|
|
|
- movl 8(%epb), %eax movl 16(%ebp), %edx
|
|
|
- movl 16(%epb), %edx pushl %edi
|
|
|
- movl (%eax,%edx,1), %edi
|
|
|
- pushl %edi
|
|
|
-
|
|
|
-because first is checked whether %eax isn't changed (it isn't) and
|
|
|
-consequently all instructions containg %eax are removed}
|
|
|
-Begin
|
|
|
- TmpResult := True;
|
|
|
- If (Pai(oldp)^.typ = ait_instruction) Then {oldp and newp are the same instruction}
|
|
|
- Case Pai386(oldp)^.op1t Of
|
|
|
- Top_Reg:
|
|
|
- If (Reg32(TRegister(Pai386(oldp)^.op1)) in RegsNotYetChecked) Then
|
|
|
- Begin
|
|
|
- RegsNotYetChecked := RegsNotYetChecked - [Reg32(TRegister(Pai386(oldp)^.op1))];
|
|
|
- If Assigned(newp^.previous)
|
|
|
- Then
|
|
|
- Begin
|
|
|
- TmpP := Pai(newp^.previous);
|
|
|
- While Assigned (TmpP^.previous) And
|
|
|
- PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do
|
|
|
- TmpP := Pai(TmpP^.previous);
|
|
|
- TmpResult := Assigned(TmpP) And
|
|
|
- RegsSameContent(oldp, TmpP, Reg32(TRegister(Pai386(oldp)^.op1)))
|
|
|
- End
|
|
|
- Else TmpResult := False;
|
|
|
- End;
|
|
|
- Top_Ref:
|
|
|
- With TReference(Pai386(oldp)^.op1^) Do
|
|
|
- Begin
|
|
|
- If (Base in RegsNotYetChecked) And
|
|
|
- (Base <> R_NO) Then
|
|
|
- Begin
|
|
|
- RegsNotYetChecked := RegsNotYetChecked - [Base];
|
|
|
- If Assigned(newp^.previous)
|
|
|
- Then
|
|
|
- Begin
|
|
|
- TmpP := Pai(newp^.previous);
|
|
|
- While Assigned (TmpP^.previous) And
|
|
|
- PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do
|
|
|
- TmpP := Pai(TmpP^.previous);
|
|
|
- TmpResult := Assigned(TmpP) And
|
|
|
- RegsSameContent(oldp, TmpP, Base)
|
|
|
- End
|
|
|
- Else TmpResult := False;
|
|
|
- End;
|
|
|
- If TmpResult And
|
|
|
- (Index <> R_NO) And
|
|
|
- (Index in RegsNotYetChecked) Then
|
|
|
- Begin
|
|
|
- RegsNotYetChecked := RegsNotYetChecked - [Index];
|
|
|
- If Assigned(newp^.previous)
|
|
|
- Then
|
|
|
- Begin
|
|
|
- TmpP := Pai(newp^.previous);
|
|
|
- While Assigned (TmpP^.previous) And
|
|
|
- PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do
|
|
|
- TmpP := Pai(TmpP^.previous);
|
|
|
- TmpResult := Assigned(TmpP) And
|
|
|
- RegsSameContent(oldp, TmpP, Index)
|
|
|
- End
|
|
|
- Else TmpResult := False;
|
|
|
- End;
|
|
|
- End;
|
|
|
- End;
|
|
|
- NoChangedRegInRef := TmpResult;
|
|
|
-End;
|
|
|
-
|
|
|
-Begin {CheckSequence}
|
|
|
- Reg := Reg32(Reg);
|
|
|
- Found := 0;
|
|
|
- hp2 := PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].StartMod;
|
|
|
- hp3 := p;
|
|
|
- EndMod := PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].StartMod;
|
|
|
- RegsNotYetChecked := [R_EAX..R_EDI];
|
|
|
- For Counter := 2 to PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods Do
|
|
|
- EndMod := Pai(EndMod^.Next);
|
|
|
- While (Found <> PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods) And
|
|
|
- InstructionsEqual(hp2, hp3) And
|
|
|
- NoChangedRegInRef(EndMod, hp3) Do
|
|
|
- Begin
|
|
|
- hp2 := Pai(hp2^.next);
|
|
|
- hp3 := Pai(hp3^.next);
|
|
|
- Inc(Found)
|
|
|
- End;
|
|
|
- If (Found <> PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods)
|
|
|
- Then
|
|
|
- Begin
|
|
|
- If ((Found+1) = PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods) And
|
|
|
- Assigned(hp2) And
|
|
|
- (Pai(hp2)^.typ = ait_instruction) And
|
|
|
- (Pai386(hp2)^._operator In [A_MOV, A_MOVZX]) And
|
|
|
- (Pai386(hp2)^.op1t = top_ref) And
|
|
|
- (Pai386(hp2)^.op2t = top_reg) And
|
|
|
- Assigned(hp3) And
|
|
|
- (Pai(hp3)^.typ = ait_instruction) And
|
|
|
- (Pai386(hp3)^._operator In [A_MOV, A_MOVZX]) And
|
|
|
- (Pai386(hp3)^.op1t = top_ref) And
|
|
|
- (Pai386(hp3)^.op2t = top_reg) And
|
|
|
- (Pai386(hp2)^._operator <> Pai386(hp3)^._operator) And
|
|
|
- RefsEqual(TReference(Pai386(hp2)^.op1^),TReference(Pai386(hp3)^.op1^)) And
|
|
|
- NoChangedRegInRef(EndMod, hp3)
|
|
|
- Then
|
|
|
- If (Pai386(hp2)^._operator = A_MOV)
|
|
|
- Then
|
|
|
- Begin
|
|
|
- If (Pai386(hp2)^.Size = S_B) And
|
|
|
- (Reg8toReg32(TRegister(Pai386(hp2)^.op2)) =
|
|
|
- TRegister(Pai386(hp3)^.op2))
|
|
|
- Then
|
|
|
- Begin
|
|
|
- Pai386(hp2)^._operator := A_MOVZX;
|
|
|
- Pai386(hp2)^.op2 := Pai386(hp3)^.op2;
|
|
|
- Pai386(hp2)^.Size := S_BL;
|
|
|
- Inc(Found);
|
|
|
- CheckSequence := True;
|
|
|
- End
|
|
|
- Else
|
|
|
- Begin
|
|
|
- CheckSequence := False;
|
|
|
- If (Found > 0) Then
|
|
|
- Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
|
|
|
- End
|
|
|
- End
|
|
|
- Else
|
|
|
- Begin
|
|
|
- If (Pai386(hp3)^.Size = S_B) And
|
|
|
- (Reg8toReg32(TRegister(Pai386(hp3)^.op2)) =
|
|
|
- TRegister(Pai386(hp2)^.op2))
|
|
|
- Then
|
|
|
- Begin
|
|
|
- CheckSequence := True;
|
|
|
- Inc(Found)
|
|
|
- End
|
|
|
- Else
|
|
|
- Begin
|
|
|
- CheckSequence := False;
|
|
|
- If (Found > 0) Then
|
|
|
- Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
|
|
|
- End
|
|
|
- End
|
|
|
- Else
|
|
|
- Begin
|
|
|
- CheckSequence := False;
|
|
|
- If (found > 0) then
|
|
|
- {this is correct because we only need to turn off the CanBeRemoved flag
|
|
|
- when an instruction has already been processed by CheckSequence
|
|
|
- (otherwise CanBeRemoved can't be true, or can't have to be turned off).
|
|
|
- If it has already been processed by checkSequence and flagged to be
|
|
|
- removed, it means that it has been checked against a previous sequence
|
|
|
- and that it was equal (otherwise CheckSequence would have returned false
|
|
|
- and the instruction wouldn't have been removed). If this "If found > 0"
|
|
|
- check is left out, incorrect optimizations are performed.}
|
|
|
- Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
|
|
|
- End
|
|
|
- End
|
|
|
- Else CheckSequence := True;
|
|
|
-End; {CheckSequence}
|
|
|
-
|
|
|
-{$Endif OptimizeMovs}
|
|
|
-
|
|
|
-Procedure DestroyAllRegs(p: Pai);
|
|
|
-Var Counter: TRegister;
|
|
|
-Begin {initializes/desrtoys all registers}
|
|
|
- For Counter := R_EAX To R_EDI Do
|
|
|
- DestroyReg(p, Counter);
|
|
|
- PPaiProp(p^.fileinfo.line)^.DirFlag := F_Unknown;
|
|
|
-End;
|
|
|
-
|
|
|
-Procedure Destroy(PaiObj: Pai; opt: Longint; Op: Pointer);
|
|
|
-Begin
|
|
|
- Case opt Of
|
|
|
- top_reg: DestroyReg(PaiObj, TRegister(Op));
|
|
|
- top_ref: DestroyRefs(PaiObj, TReference(Op^), R_NO);
|
|
|
- top_symbol:;
|
|
|
- End;
|
|
|
-End;
|
|
|
-
|
|
|
-Function CreateRegs(First: Pai): Pai;
|
|
|
-{Starts creating the reg contents for the instructions starting with p.
|
|
|
-Returns the last pai which has been processed}
|
|
|
-Var
|
|
|
- TmpProp: PPaiProp;
|
|
|
- Cnt, InstrCnt: Longint;
|
|
|
- InstrProp: TAsmInstrucProp;
|
|
|
- p: Pai;
|
|
|
- TmpRef: TReference;
|
|
|
- TmpReg: TRegister;
|
|
|
-Begin
|
|
|
- p := First;
|
|
|
- InstrCnt := 1;
|
|
|
- FillChar(NrOfInstrSinceLastMod, SizeOf(NrOfInstrSinceLastMod), 0);
|
|
|
- While Assigned(p) Do
|
|
|
- Begin
|
|
|
- CreateRegs := p;
|
|
|
- If (InstrCnt <= NrOfPaiFast)
|
|
|
- Then TmpProp := @PaiPropBlock^[InstrCnt]
|
|
|
- Else New(TmpProp);
|
|
|
- If (p <> First)
|
|
|
- Then TmpProp^ := PPaiProp(Pai(p^.previous)^.fileinfo.line)^
|
|
|
- Else FillChar(TmpProp^, SizeOf(TmpProp^), 0);
|
|
|
- TmpProp^.linesave := p^.fileinfo.line;
|
|
|
- PPaiProp(p^.fileinfo.line) := TmpProp;
|
|
|
- For TmpReg := R_EAX To R_EDI Do
|
|
|
- Inc(NrOfInstrSinceLastMod[TmpReg]);
|
|
|
- Case p^.typ Of
|
|
|
- ait_label: DestroyAllRegs(p);
|
|
|
- ait_labeled_instruction
|
|
|
-{$ifdef GDB}
|
|
|
- , ait_stabs, ait_stabn,
|
|
|
- ait_stab_function_name
|
|
|
-{$endif GDB}
|
|
|
- :; {nothing changes}
|
|
|
-{$ifdef regalloc}
|
|
|
- ait_regalloc, ait_regdealloc:;
|
|
|
-{$endif regalloc}
|
|
|
- ait_instruction:
|
|
|
- Begin
|
|
|
- InstrProp := AsmInstr[Pai386(p)^._operator];
|
|
|
- Case Pai386(p)^._operator Of
|
|
|
-{$IfDef OptimizeMovs}
|
|
|
- A_MOV, A_MOVZX, A_MOVSX:
|
|
|
- Begin
|
|
|
- Case Pai386(p)^.op1t Of
|
|
|
- Top_Reg:
|
|
|
- Case Pai386(p)^.op2t Of
|
|
|
- Top_Reg:
|
|
|
- Begin
|
|
|
- DestroyReg(p, TRegister(Pai386(p)^.op2));
|
|
|
-{ TmpProp^.Regs[TRegister(Pai386(p)^.op2)] :=
|
|
|
- TmpProp^.Regs[TRegister(Pai386(p)^.op1)];
|
|
|
- If (TmpProp^.Regs[TRegister(Pai386(p)^.op2)].ModReg = R_NO) Then
|
|
|
- TmpProp^.Regs[TRegister(Pai386(p)^.op2)].ModReg :=
|
|
|
- Tregister(Pai386(p)^.op1);}
|
|
|
- End;
|
|
|
- Top_Ref: DestroyRefs(p, TReference(Pai386(p)^.op2^), TRegister(Pai386(p)^.op1));
|
|
|
- End;
|
|
|
- Top_Ref:
|
|
|
- Begin {destination is always a register in this case}
|
|
|
- TmpReg := Reg32(TRegister(Pai386(p)^.op2));
|
|
|
- If (RegInRef(TmpReg, TReference(Pai386(p)^.op1^)))
|
|
|
- Then
|
|
|
- Begin
|
|
|
- With PPaiProp(Pai(p)^.fileinfo.line)^.Regs[TmpReg] Do
|
|
|
- Begin
|
|
|
- Inc(State);
|
|
|
- {also store how many instructions are part of the sequence in the first
|
|
|
- instructions PPaiProp, so it can be easily accessed from within
|
|
|
- CheckSequence}
|
|
|
- If (typ <> Con_Ref) Then
|
|
|
- Begin
|
|
|
- typ := Con_Ref;
|
|
|
- StartMod := p;
|
|
|
- End;
|
|
|
- Inc(NrOfMods, NrOfInstrSinceLastMod[TmpReg]);
|
|
|
- PPaiProp(Pai(StartMod)^.fileinfo.line)^.Regs[TmpReg].NrOfMods := NrOfMods;
|
|
|
- NrOfInstrSinceLastMod[TmpReg] := 0;
|
|
|
- End;
|
|
|
- End
|
|
|
- Else
|
|
|
- Begin
|
|
|
- DestroyReg(p, TmpReg);
|
|
|
- With PPaiProp(Pai(p)^.fileinfo.line)^.Regs[TmpReg] Do
|
|
|
- Begin
|
|
|
- Typ := Con_Ref;
|
|
|
- StartMod := p;
|
|
|
- NrOfMods := 1;
|
|
|
- End;
|
|
|
- End;
|
|
|
- End;
|
|
|
- Top_Const:
|
|
|
- Begin
|
|
|
- Case Pai386(p)^.op2t Of
|
|
|
- Top_Reg:
|
|
|
- Begin
|
|
|
- TmpReg := Reg32(TRegister(Pai386(p)^.op2));
|
|
|
- With TmpProp^.Regs[TmpReg] Do
|
|
|
- Begin
|
|
|
- {it doesn't matter that the state is changed,
|
|
|
- it isn't looked at when removing constant reloads}
|
|
|
- DestroyReg(p, TmpReg);
|
|
|
- typ := Con_Const;
|
|
|
- StartMod := Pai386(p)^.op1;
|
|
|
- End
|
|
|
- End;
|
|
|
- Top_Ref: DestroyRefs(P, TReference(Pai386(p)^.op2^), R_NO);
|
|
|
- End;
|
|
|
- End;
|
|
|
- End;
|
|
|
- End;
|
|
|
-{$EndIf OptimizeMovs}
|
|
|
- A_IMUL:
|
|
|
- Begin
|
|
|
- If (Pai386(p)^.Op3t = top_none)
|
|
|
- Then
|
|
|
- If (Pai386(p)^.Op2t = top_none)
|
|
|
- Then
|
|
|
- Begin
|
|
|
- DestroyReg(p, R_EAX);
|
|
|
- DestroyReg(p, R_EDX)
|
|
|
- End
|
|
|
- Else
|
|
|
- Begin
|
|
|
- If (Pai386(p)^.Op2t = top_reg) Then
|
|
|
- DestroyReg(p, TRegister(Pai386(p)^.Op2));
|
|
|
- End
|
|
|
- Else If (Pai386(p)^.Op3t = top_reg) Then
|
|
|
- DestroyReg(p, TRegister(longint(twowords(Pai386(p)^.Op2).word2)));
|
|
|
- End;
|
|
|
- A_XOR:
|
|
|
- Begin
|
|
|
- If (Pai386(p)^.op1t = top_reg) And
|
|
|
- (Pai386(p)^.op2t = top_reg) And
|
|
|
- (Pai386(p)^.op1 = Pai386(p)^.op2)
|
|
|
- Then
|
|
|
- Begin
|
|
|
- DestroyReg(p, Tregister(Pai386(p)^.op1));
|
|
|
- TmpProp^.Regs[Reg32(Tregister(Pai386(p)^.op1))].typ := Con_Const;
|
|
|
- TmpProp^.Regs[Reg32(Tregister(Pai386(p)^.op1))].StartMod := Pointer(0)
|
|
|
- End
|
|
|
- Else Destroy(p, Pai386(p)^.op2t, Pai386(p)^.op2);
|
|
|
- End
|
|
|
- Else
|
|
|
- Begin
|
|
|
- If InstrProp.NCh <> 255
|
|
|
- Then
|
|
|
- For Cnt := 1 To InstrProp.NCh Do
|
|
|
- Case InstrProp.Ch[Cnt] Of
|
|
|
- C_None:;
|
|
|
- C_EAX..C_EDI: DestroyReg(p, TCh2Reg(InstrProp.Ch[Cnt]));
|
|
|
- C_CDirFlag: PPaiProp(Pai(p)^.fileinfo.line)^.DirFlag := F_NotSet;
|
|
|
- C_SDirFlag: PPaiProp(Pai(p)^.fileinfo.line)^.DirFlag := F_Set;
|
|
|
- C_Op1: Destroy(p, Pai386(p)^.op1t, Pai386(p)^.op1);
|
|
|
- C_Op2: Destroy(p, Pai386(p)^.op2t, Pai386(p)^.op2);
|
|
|
- C_Op3: Destroy(p, Pai386(p)^.op2t, Pointer(Longint(TwoWords(Pai386(p)^.op2).word2)));
|
|
|
- C_MemEDI:
|
|
|
- Begin
|
|
|
- FillChar(TmpRef, SizeOf(TmpRef), 0);
|
|
|
- TmpRef.Base := R_EDI;
|
|
|
- DestroyRefs(p, TmpRef, R_NO)
|
|
|
- End;
|
|
|
- C_Flags, C_FPU:;
|
|
|
- End
|
|
|
- Else
|
|
|
- Begin
|
|
|
- DestroyAllRegs(p);
|
|
|
- End;
|
|
|
- End;
|
|
|
- End;
|
|
|
- End
|
|
|
- Else
|
|
|
- Begin
|
|
|
- DestroyAllRegs(p);
|
|
|
- End;
|
|
|
- End;
|
|
|
- Inc(InstrCnt);
|
|
|
- p := Pai(p^.next);
|
|
|
- End;
|
|
|
-End;
|
|
|
-
|
|
|
-Procedure OptimizeBlock(First, Last: Pai);
|
|
|
-{marks the instructions that can be removed by RemoveInstructs. They're not
|
|
|
- removed immediately because sometimes an instruction needs to be checked in
|
|
|
- two different sequences}
|
|
|
-Var Cnt, Cnt2: Longint;
|
|
|
- p, hp1, hp2: Pai;
|
|
|
-Begin
|
|
|
- p := First;
|
|
|
- While (p <> Pai(Last^.Next)) Do
|
|
|
- Begin
|
|
|
- Case p^.typ Of
|
|
|
- ait_label, ait_labeled_instruction:;
|
|
|
- ait_instruction:
|
|
|
- Begin
|
|
|
- Case Pai386(p)^._operator Of
|
|
|
- A_CLD: If Assigned(p^.previous) And
|
|
|
- (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.DirFlag = F_NotSet) Then
|
|
|
- PPaiProp(Pai(p)^.fileinfo.line)^.CanBeRemoved := True;
|
|
|
-{$IfDef OptimizeMovs}
|
|
|
- A_MOV, A_MOVZX, A_MOVSX:
|
|
|
- Begin
|
|
|
- Case Pai386(p)^.op1t Of
|
|
|
-{ Top_Reg:
|
|
|
- Case Pai386(p)^.op2t Of
|
|
|
- Top_Reg:;
|
|
|
- Top_Ref:;
|
|
|
- End;}
|
|
|
- Top_Ref:
|
|
|
- Begin {destination is always a register in this case}
|
|
|
- With PPaiProp(p^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op2))] Do
|
|
|
- Begin
|
|
|
- If Assigned(p^.previous) And
|
|
|
- (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.
|
|
|
- Regs[Reg32(TRegister(Pai386(p)^.op2))].typ = con_ref) Then
|
|
|
- {so we don't try to check a sequence when the register only contains a constant}
|
|
|
- If CheckSequence(p, TRegister(Pai386(p)^.op2), Cnt) And
|
|
|
- (Cnt > 0)
|
|
|
- Then
|
|
|
- Begin
|
|
|
- hp1 := nil;
|
|
|
- {although it's perfectly ok to remove an instruction which doesn't contain
|
|
|
- the register that we've just checked (CheckSequence takes care of that),
|
|
|
- the sequence containing this other register should also be completely
|
|
|
- checked and removed, otherwise we may get situations like this:
|
|
|
-
|
|
|
- movl 12(%ebp), %edx movl 12(%ebp), %edx
|
|
|
- movl 16(%ebp), %eax movl 16(%ebp), %eax
|
|
|
- movl 8(%edx), %edx movl 8(%edx), %edx
|
|
|
- movl (%eax), eax movl (%eax), eax
|
|
|
- cmpl %eax, %edx cmpl %eax, %edx
|
|
|
- jnz l123 getting converted to jnz l123
|
|
|
- movl 12(%ebp), %edx movl 4(%eax), eax
|
|
|
- movl 16(%ebp), %eax
|
|
|
- movl 8(%edx), %edx
|
|
|
- movl 4(%eax), eax}
|
|
|
- hp2 := p;
|
|
|
- For Cnt2 := 1 to Cnt Do
|
|
|
- Begin
|
|
|
- { Note to Jonas :
|
|
|
- ait_stab_function_name is only at the begin of one function
|
|
|
- ait_stabn is only inserted in ag so you should not see any
|
|
|
- ait_stabs are only in head and tail of procs
|
|
|
- so you should no have problems with those neither !! (PM)
|
|
|
- Tell me if I am wrong
|
|
|
- If Not(Pai(p)^.typ In [ait_stabs, ait_stabn, ait_stab_function_name]) Then }
|
|
|
- Begin
|
|
|
- If (hp1 = nil) And
|
|
|
- Not(RegInInstruction(Tregister(Pai386(hp2)^.op2), p))
|
|
|
- Then hp1 := p;
|
|
|
- PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True;
|
|
|
- End;
|
|
|
- p := Pai(p^.next);
|
|
|
- End;
|
|
|
- If hp1 <> nil Then p := hp1;
|
|
|
- Continue;
|
|
|
- End
|
|
|
- Else
|
|
|
- If (Cnt > 0) And
|
|
|
- (PPaiProp(p^.fileinfo.line)^.CanBeRemoved) Then
|
|
|
- Begin
|
|
|
- hp2 := p;
|
|
|
- For Cnt2 := 1 to Cnt Do
|
|
|
- Begin
|
|
|
- If RegInInstruction(Tregister(Pai386(hp2)^.op2), p)
|
|
|
- Then PPaiProp(p^.fileinfo.line)^.CanBeRemoved := False;
|
|
|
- p := Pai(p^.Next)
|
|
|
- End;
|
|
|
- Continue;
|
|
|
- End;
|
|
|
- End;
|
|
|
- End;
|
|
|
- Top_Const:
|
|
|
- Begin
|
|
|
- Case Pai386(p)^.op2t Of
|
|
|
- Top_Reg:
|
|
|
- Begin
|
|
|
- If Assigned(p^.previous) Then
|
|
|
- With PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg32(TRegister(Pai386(p)^.op2))] Do
|
|
|
- If (Typ = Con_Const) And
|
|
|
- (StartMod = Pai386(p)^.op1) Then
|
|
|
- PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True;
|
|
|
- End;
|
|
|
- Top_Ref:;
|
|
|
- End;
|
|
|
- End;
|
|
|
- End;
|
|
|
- End;
|
|
|
-{$EndIf OptimizeMovs}
|
|
|
- A_STD: If Assigned(p^.previous) And
|
|
|
- (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.DirFlag = F_Set) Then
|
|
|
- PPaiProp(Pai(p)^.fileinfo.line)^.CanBeRemoved := True;
|
|
|
- A_XOR:
|
|
|
- Begin
|
|
|
- If (Pai386(p)^.op1t = top_reg) And
|
|
|
- (Pai386(p)^.op2t = top_reg) And
|
|
|
- (Pai386(p)^.op1 = Pai386(p)^.op2) And
|
|
|
- Assigned(p^.previous) And
|
|
|
- (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].typ = con_const) And
|
|
|
- (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].StartMod = Pointer(0))
|
|
|
- Then PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True
|
|
|
- End
|
|
|
- End
|
|
|
- End;
|
|
|
- End;
|
|
|
- p := Pai(p^.next);
|
|
|
- End;
|
|
|
-End;
|
|
|
-
|
|
|
-Procedure RemoveInstructs(First, Last: Pai);
|
|
|
-{Removes the marked instructions and disposes the PPaiProps of the other
|
|
|
- instructions, restoring theirline number}
|
|
|
-Var p, hp1: Pai;
|
|
|
- TmpLine, InstrCnt: Longint;
|
|
|
-Begin
|
|
|
- p := First;
|
|
|
- InstrCnt := 1;
|
|
|
- While (p <> Pai(Last^.Next)) Do
|
|
|
- If PPaiProp(p^.fileinfo.line)^.CanBeRemoved
|
|
|
- Then
|
|
|
- Begin
|
|
|
- If (InstrCnt > NrOfPaiFast) Then
|
|
|
- Dispose(PPaiProp(p^.fileinfo.line));
|
|
|
- hp1 := Pai(p^.Next);
|
|
|
- AsmL^.Remove(p);
|
|
|
- Dispose(p, Done);
|
|
|
- p := hp1;
|
|
|
- Inc(InstrCnt)
|
|
|
- End
|
|
|
- Else
|
|
|
- Begin
|
|
|
- If (InstrCnt > NrOfPaiFast)
|
|
|
- Then
|
|
|
- Begin
|
|
|
- TmpLine := PPaiProp(p^.fileinfo.line)^.linesave;
|
|
|
- Dispose(PPaiProp(p^.fileinfo.line));
|
|
|
- p^.fileinfo.line := TmpLine;
|
|
|
- End
|
|
|
- Else p^.fileinfo.line := PPaiProp(p^.fileinfo.line)^.linesave;
|
|
|
- p := Pai(p^.Next);
|
|
|
- Inc(InstrCnt)
|
|
|
- End;
|
|
|
- If (NrOfPaiFast > 0) Then
|
|
|
-{$IfDef TP}
|
|
|
- Freemem(PaiPropBlock, NrOfPaiFast*(((SizeOf(TPaiProp)+1)div 2)*2))
|
|
|
-{$Else}
|
|
|
- FreeMem(PaiPropBlock, NrOfPaiFast*(((SizeOf(TPaiProp)+3)div 4)*4))
|
|
|
-{$EndIf TP}
|
|
|
-End;
|
|
|
-
|
|
|
-Function InitReloadOpt(AsmL: PAasmOutput): Boolean;
|
|
|
-{reserves memory for the PPaiProps in one big memory block when not using
|
|
|
- TP, returns False if not enough memory is available for the optimizer in all
|
|
|
- cases}
|
|
|
-Var p: Pai;
|
|
|
-Begin
|
|
|
- P := Pai(AsmL^.First);
|
|
|
- NrOfPaiObjs := 1;
|
|
|
- While (P <> Pai(AsmL^.last)) Do
|
|
|
- Begin
|
|
|
- Inc(NrOfPaiObjs);
|
|
|
- P := Pai(P^.next)
|
|
|
- End;
|
|
|
-{$IfDef TP}
|
|
|
- If (MemAvail < (SizeOf(TPaiProp)*NrOfPaiObjs))
|
|
|
- {this doesn't have to be one contiguous block}
|
|
|
- Then InitReloadOpt := False
|
|
|
- Else
|
|
|
- Begin
|
|
|
- InitReloadOpt := True;
|
|
|
- If (MaxAvail < 65520)
|
|
|
- Then NrOfPaiFast := MaxAvail Div (((SizeOf(TPaiProp)+1) div 2)*2)
|
|
|
- Else NrOfPaiFast := 65520 Div (((SizeOf(TPaiProp)+1) div 2)*2);
|
|
|
- If (NrOfPaiFast > 0) Then
|
|
|
- GetMem(PaiPropBlock, NrOfPaiFast*(((SizeOf(TPaiProp)+1) div 2)*2));
|
|
|
- End;
|
|
|
-{$Else}
|
|
|
-{Uncomment the next line to see how much memory the reloading optimizer needs}
|
|
|
-{ Writeln((NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4)));}
|
|
|
-{no need to check mem/maxavail, we've got as much virtual memory as we want}
|
|
|
- InitReloadOpt := True;
|
|
|
- GetMem(PaiPropBlock, NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4));
|
|
|
- InitReloadOpt := True;
|
|
|
- NrOfPaiFast := NrOfPaiObjs;
|
|
|
- {$EndIf TP}
|
|
|
-End;
|
|
|
-
|
|
|
-Var BlockEnd: Pai;
|
|
|
-
|
|
|
-Begin {ReloadOpt}
|
|
|
- If InitReloadOpt(AsmL)
|
|
|
- Then
|
|
|
- Begin
|
|
|
- BlockEnd := CreateRegs(Pai(AsmL^.First));
|
|
|
- OptimizeBlock(Pai(AsmL^.First), BlockEnd);
|
|
|
- RemoveInstructs(Pai(AsmL^.First), BlockEnd)
|
|
|
- End;
|
|
|
-End;
|
|
|
-
|
|
|
-{
|
|
|
- $Log$
|
|
|
- Revision 1.7 1998-07-14 14:46:41 peter
|
|
|
- * released NEWINPUT
|
|
|
-
|
|
|
- Revision 1.6 1998/05/06 08:38:33 pierre
|
|
|
- * better position info with UseTokenInfo
|
|
|
- UseTokenInfo greatly simplified
|
|
|
- + added check for changed tree after first time firstpass
|
|
|
- (if we could remove all the cases were it happen
|
|
|
- we could skip all firstpass if firstpasscount > 1)
|
|
|
- Only with ExtDebug
|
|
|
-
|
|
|
- Revision 1.5 1998/04/29 10:33:42 pierre
|
|
|
- + added some code for ansistring (not complete nor working yet)
|
|
|
- * corrected operator overloading
|
|
|
- * corrected nasm output
|
|
|
- + started inline procedures
|
|
|
- + added starstarn : use ** for exponentiation (^ gave problems)
|
|
|
- + started UseTokenInfo cond to get accurate positions
|
|
|
-
|
|
|
- Revision 1.4 1998/04/21 11:30:14 peter
|
|
|
- * fixed $ifdef regalloc
|
|
|
-
|
|
|
- Revision 1.3 1998/04/16 16:53:56 jonas
|
|
|
- *** empty log message ***
|
|
|
-
|
|
|
- Revision 1.2 1998/04/06 22:42:32 jonas
|
|
|
- + removal of superflouos cld/std instructions
|
|
|
-
|
|
|
- Revision 1.1.1.1 1998/03/25 11:18:12 root
|
|
|
- * Restored version
|
|
|
-
|
|
|
- Revision 1.22 1998/03/24 21:48:29 florian
|
|
|
- * just a couple of fixes applied:
|
|
|
- - problem with fixed16 solved
|
|
|
- - internalerror 10005 problem fixed
|
|
|
- - patch for assembler reading
|
|
|
- - small optimizer fix
|
|
|
- - mem is now supported
|
|
|
-
|
|
|
- Revision 1.21 1998/03/11 15:45:35 florian
|
|
|
- * -Oa problem solved
|
|
|
-
|
|
|
- Revision 1.20 1998/03/10 01:17:13 peter
|
|
|
- * all files have the same header
|
|
|
- * messages are fully implemented, EXTDEBUG uses Comment()
|
|
|
- + AG... files for the Assembler generation
|
|
|
-
|
|
|
- Revision 1.19 1998/03/09 16:46:27 jonas
|
|
|
- * fixed bug with uncertain optimizations when moving data among variables using movsl
|
|
|
-
|
|
|
- Revision 1.18 1998/03/04 16:42:00 jonas
|
|
|
- * bugfix in destroyrefs and fixed a potential bug in createregs
|
|
|
-
|
|
|
- Revision 1.17 1998/03/03 20:33:29 jonas
|
|
|
- * TContent record now only occupies 8 bytes anymore
|
|
|
-
|
|
|
- Revision 1.15 1998/03/03 01:08:13 florian
|
|
|
- * bug0105 and bug0106 problem solved
|
|
|
-
|
|
|
- Revision 1.14 1998/03/02 21:35:16 jonas
|
|
|
- * added comments from last update
|
|
|
-
|
|
|
- Revision 1.13 1998/03/02 21:29:06 jonas
|
|
|
- * redesigned TContent record so it occupies only 13 bytes anymore (was about 18)
|
|
|
- * store TPaiProps of 16 and 8 bit registers in those of the 32 bit regs
|
|
|
- * fixed a small bug which prevented some optimizes from being performed
|
|
|
- * store TPaiProps in one big array instead of in seperate records
|
|
|
- * warning: TP version not tested because I only have TP, not BP (-> no proteced mode apps)
|
|
|
-
|
|
|
- Revision 1.12 1998/02/24 21:18:13 jonas
|
|
|
- * file name back to lower case
|
|
|
-
|
|
|
- Revision 1.4 1998/02/24 20:32:12 jonas
|
|
|
- * added comments from latest commit
|
|
|
-
|
|
|
- Revision 1.3 1998/02/24 20:27:51 jonas
|
|
|
- * if a register is being written to memory, it's contents aren't destroyed
|
|
|
- (wherever it's been written to, its contents are up-to-date)
|
|
|
- * changed the order in which some functions/procedure are defined, because some
|
|
|
- of them are now used by aopt386.pas
|
|
|
-
|
|
|
- Revision 1.11 1998/02/19 22:46:54 peter
|
|
|
- * Fixed linebreaks
|
|
|
-
|
|
|
- Revision 1.10 1998/02/13 10:34:31 daniel
|
|
|
- * Made Motorola version compilable.
|
|
|
- * Fixed optimizer
|
|
|
-
|
|
|
- Revision 1.9 1998/02/12 17:18:49 florian
|
|
|
- * fixed to get remake3 work, but needs additional fixes (output, I don't like
|
|
|
- also that aktswitches isn't a pointer)
|
|
|
-
|
|
|
- Revision 1.8 1998/02/12 11:49:37 daniel
|
|
|
- Yes! Finally! After three retries, my patch!
|
|
|
-
|
|
|
- Changes:
|
|
|
-
|
|
|
- Complete rewrite of psub.pas.
|
|
|
- Added support for DLL's.
|
|
|
- Compiler requires less memory.
|
|
|
- Platform units for each platform.
|
|
|
-
|
|
|
- Revision 1.7 1998/02/07 10:11:19 michael
|
|
|
- * RefsEqual made less harsh:
|
|
|
-
|
|
|
- * when something is written to x(%ebp), registers which contain
|
|
|
- a pointer that isn't "x(%ebp)"-based isn't destroyed
|
|
|
-
|
|
|
- * when something is written to a pointer location, registers
|
|
|
- which contain the contents of x(%ebp) aren't destroyed
|
|
|
-
|
|
|
-
|
|
|
- Revision 1.6 1998/01/12 17:45:20 jonas
|
|
|
- * merged DisposeProps and RemoveInstructs procedures (speed!)
|
|
|
-
|
|
|
- Revision 1.5 1998/01/11 22:51:30 jonas
|
|
|
- * back to unix linebreaks...(hate it! :)
|
|
|
-
|
|
|
- Revision 1.4 1998/01/11 22:50:10 jonas
|
|
|
- * all floating point store operations now change op1 instead of the fpu regs
|
|
|
-
|
|
|
- Revision 1.3 1998/01/11 14:40:04 jonas
|
|
|
- * bugfix in optimize procedure (too many instructions were removed in certain cases)
|
|
|
-
|
|
|
- Revision 1.1 1997/12/30 21:10:34 jonas
|
|
|
- * changed back to unix/linux line breaks
|
|
|
-
|
|
|
-
|
|
|
- Pre-CVS log:
|
|
|
-
|
|
|
-
|
|
|
- JM Jonas Maebe
|
|
|
-
|
|
|
- + feature added
|
|
|
- - removed
|
|
|
- * bug fixed or changed
|
|
|
-
|
|
|
- History (started on 2nd December 1997):
|
|
|
- 2nd December 1997:
|
|
|
- + initial version (JM)
|
|
|
- + removes redundant "xor %reg, %reg"'s (JM)
|
|
|
- 3rd December 1997:
|
|
|
- + removes certain redundant movs (still bugged) (JM)
|
|
|
- * A_REP now destroys ECX
|
|
|
- 4th December 1997:
|
|
|
- * fixed bugs in mov-removal (still bugged) (JM)
|
|
|
- 5th December 1997:
|
|
|
- * fixed more bugs in mov-removal (a compiler compiled with these
|
|
|
- optimizations now can compile itself suyccessfully!) and enhanced
|
|
|
- it (introducing new bugs, which have to be fixed again...) (JM)
|
|
|
- * A_AND and A_OR now destroy op2 instead of op1 <g> (JM)
|
|
|
- 6th December 1997:
|
|
|
- * A_PUSHAD now only destroys ESP instead of all registers (JM)
|
|
|
- * A_REPE and A_REPNE now also destroy ECX (JM)
|
|
|
- * Rewrote some procedures so it's a bit more modular and easier/
|
|
|
- cleaner/possible to do some optimizations, but it's slower (JM)
|
|
|
- * enabled mov-reloading optimization for A_MOVZX and A_MOVSX
|
|
|
- (actually it's already 7 December, 1:25 am in the mean time :) (JM)
|
|
|
- 7th December 1997:
|
|
|
- * All instructions okayed by CheckSequence are now being removed (JM)
|
|
|
-
|
|
|
-
|
|
|
- To Do:
|
|
|
- * special case for A_XCHG
|
|
|
- * implementation of ModReg comparing
|
|
|
- * special case for lea
|
|
|
- * fpu optimizing
|
|
|
- * active optimizing (ie. change certain register allocations)
|
|
|
- * make DestroyRefs a little less harsh
|
|
|
- * bug fixes?
|
|
|
-}
|