Browse Source

* split the optimizer

Jonas Maebe 27 years ago
parent
commit
892964eaf2
4 changed files with 3004 additions and 1938 deletions
  1. 23 1938
      compiler/aopt386.pas
  2. 397 0
      compiler/csopt386.pas
  3. 1208 0
      compiler/daopt386.pas
  4. 1376 0
      compiler/popt386.pas

+ 23 - 1938
compiler/aopt386.pas

@@ -1,8 +1,9 @@
 {
     $Id$
-    Copyright (c) 1993-98 by Florian Klaempfl and Jonas Maebe
+    Copyright (c) 1998 by Jonas Maebe
 
-    This unit does optimizations on the assembler code for i386+
+    This unit calls the optimization procedures to optimize the assembler
+    code 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
@@ -22,1950 +23,34 @@
 }
 Unit aopt386;
 
-  interface
+Interface
 
-    uses aasm;
+Uses aasm;
 
-    { does simple optimizations like jumps and remove pop/pushes }
-    procedure peepholeopt(asml : paasmoutput);
+Procedure Optimize(AsmL: PAasmOutput);
 
-  implementation
+Implementation
 
-    uses
-       cobjects,globals,systems,symtable,strings,verbose,hcodegen
-{$ifdef i386}
-       ,i386
-       ,cgi386
-{$else}
-{$endif}
-       ;
+Uses CObjects, globals, systems, strings, verbose, hcodegen
+   {$ifdef i386}
+     ,i386, cgi386, DAOpt386, POpt386, CSOpt386
+   {$endif i386}
+     ;
 
-        {ait_* types which don't result in executable code or which don't
-         influence the way the program runs/behaves}
-  Const SkipInstr = [ait_comment
-{$ifdef GDB}
-  ,ait_stabs, ait_stabn, ait_stab_function_name
-{$endif GDB}
-{$ifdef regalloc}
-                     ,ait_regalloc, ait_regdealloc
-{$endif regalloc}
-                     ];
-
-  Type
-{$ifdef tp}
-       TLabelTable = Array[0..10000] Of Pai;
-{$else}
-       TLabelTable = Array[0..2500000] Of Pai;
-{$endif}
-       PLabelTable = ^TLabelTable;
-       twowords=record
-                word1,word2:word;
-            end;
-
-
-Var LoLab, HiLab, LabDif: Longint;
-    LTable: PLabelTable;
-
-  Function RefsEqual(const r1,r2 : treference) : boolean;
-
-  begin
-     if r1.isintvalue
-       then RefsEqual:=r2.isintvalue and (r1.offset=r2.offset)
-       else if (r1.offset=r2.offset) and (r1.base=r2.base) and
-               (r1.index=r2.index) and (r1.segment=r2.segment) and
-               (r1.scalefactor=r2.scalefactor)
-              then
-                begin
-                  if assigned(r1.symbol)
-                    then RefsEqual:=assigned(r2.symbol) and (r1.symbol^=r2.symbol^)
-                    else RefsEqual:=not(assigned(r2.symbol));
-                end
-              Else RefsEqual := False;
-  end;
-
-Function Reg32(Reg: TRegister): TRegister;
-{Returns the 32 bit component of Reg if it exists, otherwise Reg is returned}
+Procedure Optimize(AsmL: PAasmOutput);
+Var BlockEnd: Pai;
 Begin
-  Reg32 := Reg;
-  If (Reg >= R_AX)
-    Then
-      If (Reg <= R_DI)
-        Then Reg32 := Reg16ToReg32(Reg)
-        Else
-          If (Reg <= R_BL)
-            Then Reg32 := Reg8toReg32(Reg);
+  DFAPass1(AsmL);
+  PeepHoleOptPass1(AsmL);
+  PeepHoleOptPass1(AsmL);
+  BlockEnd := DFAPass2(AsmL);
+  If BlockEnd <> Nil Then
+    CSE(AsmL, Pai(AsmL^.First), BlockEnd);
+  PeepHoleOptPass2(AsmL);
 End;
 
-Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
-Begin {checks whether Ref contains a reference to Reg}
-  Reg := Reg32(Reg);
-  RegInRef := (Ref.Base = Reg) Or (Ref.Index = Reg)
-End;
-
-Function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
-{checks if Reg is used by the instruction p1}
-Var TmpResult: Boolean;
-Begin
-  TmpResult := False;
-  If (Pai(p1)^.typ = ait_instruction) Then
-    Begin
-      Case Pai386(p1)^.op1t Of
-        Top_Reg: TmpResult := Reg = TRegister(Pai386(p1)^.op1);
-        Top_Ref: TmpResult := RegInRef(Reg, TReference(Pai386(p1)^.op1^))
-      End;
-      If Not(TmpResult) Then
-        Case Pai386(p1)^.op2t Of
-          Top_Reg:
-              if Pai386(p1)^.op3t<>Top_reg
-                then TmpResult := Reg = TRegister(Pai386(p1)^.op2)
-                else TmpResult := longint(Reg) = twowords(Pai386(p1)^.op2).word1;
-          Top_Ref: TmpResult := RegInRef(Reg, TReference(Pai386(p1)^.op2^))
-        End;
-      If Not(TmpResult) Then
-        Case Pai386(p1)^.op3t Of
-          Top_Reg: TmpResult := longint(Reg) =twowords(Pai386(p1)^.op2).word2;
-          Top_none:;
-          else
-             internalerror($Da);
-       End
-    End;
-  RegInInstruction := TmpResult
-End;
-
-{$i aopt386.inc}
-{aopt386.inc contains the reloading optimizer}
-
-  Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
-  {skips ait_regalloc, ait_regdealloc and ait_stab* objects and puts the
-   next pai object in Next. Returns false if there isn't any}
-  Begin
-    GetNextInstruction := False;
-    Current := Pai(Current^.Next);
-    While Assigned(Current) And
-          (Pai(Current)^.typ In SkipInstr) Do
-      Current := Pai(Current^.Next);
-    If Assigned(Current)
-      Then
-        Begin
-          Next := Current;
-          GetNextInstruction := True;
-        End;
-  End;
-
-  Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
-  {skips the ait-types in SkipInstr puts the previous pai object in
-   Last. Returns false if there isn't any}
-  Begin
-    GetLastInstruction := False;
-    Current := Pai(Current^.previous);
-    While Assigned(Current) And
-          (Pai(Current)^.typ In SkipInstr) Do
-      Current := Pai(Current^.previous);
-    If Assigned(Current)
-      Then
-        Begin
-          Last := Current;
-          GetLastInstruction := True;
-        End;
-  End;
-
-  Function FindLabel(L: PLabel; Var hp: Pai): Boolean;
-
-  {searches for the specified label starting from hp as long as the
-   encountered instructions are labels, to be able to optimize constructs like
-
-   jne l2              jmp l2
-   jmp l3     and      l1:
-   l1:                 l2:
-   l2:}
-
-  Var TempP: Pai;
-
-  Begin
-    TempP := hp;
-    While Assigned(TempP) and
-         (pai(TempP)^.typ In SkipInstr + [ait_label]) Do
-      If (pai_label(TempP)^.l <> L)
-        Then TempP := Pai(TempP^.next)
-        Else
-          Begin
-            hp := TempP;
-            FindLabel := True;
-            exit
-          End;
-    FindLabel := False
-  End;
-
-  Function PowerOf2(L: Longint): Longint;
-  Var Counter, TempVal: Longint;
-  Begin
-    TempVal := 1;
-    For Counter := 1 to L Do
-      TempVal := TempVal * 2;
-    PowerOf2 := TempVal;
-  End;
-
-  Procedure DoOptimize(asml : paasmoutput);
-
-  var
-      p,hp1,hp2 : pai;
-      TmpBool1, TmpBool2: Boolean;
-
-      TmpRef: PReference;
-
-      RegsUsed: Set of TRegister;
-
-    { inserts new_one between prev and foll }
-    Procedure InsertLLItem(prev, foll, new_one: PLinkedList_Item);
-    Begin
-      If Assigned(prev)
-        Then
-          If Assigned(foll)
-            Then
-              Begin
-                If Assigned(new_one) Then
-                  Begin
-                    new_one^.previous := prev;
-                    new_one^.next := foll;
-                    prev^.next := new_one;
-                    foll^.previous := new_one;
-                  End;
-              End
-            Else AsmL^.Concat(new_one)
-        Else If Assigned(Foll) Then AsmL^.Insert(new_one)
-    End;
-
-    Procedure GetFinalDestination(hp: pai_labeled);
-    {traces sucessive jumps to their final destination and sets it, e.g.
-    je l1                je l3
-    <code>               <code>
-    l1:       becomes    l1:
-    je l2                je l3
-    <code>               <code>
-    l2:                  l2:
-    jmp l3               jmp l3}
-
-    Var p1: pai;
-
-      Function SkipLabels(hp: Pai): Pai;
-      {skips all labels and returns the next "real" instruction; it is
-       assumed that hp is of the type ait_label}
-      Begin
-        While assigned(hp^.next) and
-              (pai(hp^.next)^.typ In SkipInstr + [ait_label]) Do
-          hp := pai(hp^.next);
-        If assigned(hp^.next)
-          Then SkipLabels := pai(hp^.next)
-          Else SkipLabels := hp;
-      End;
-
-    Begin
-      If (hp^.lab^.nb >= LoLab) and
-         (hp^.lab^.nb <= HiLab) and   {range check, necessary?}
-         (Pointer(LTable^[hp^.lab^.nb-LoLab]) <> Pointer(0)) Then
-        Begin
-          p1 := LTable^[hp^.lab^.nb-LoLab]; {the jump's destination}
-          p1 := SkipLabels(p1);
-          If (pai(p1)^.typ = ait_labeled_instruction) and
-             ((pai_labeled(p1)^._operator = A_JMP) or
-              (pai_labeled(p1)^._operator = hp^._operator))
-            Then
-              Begin
-                GetFinalDestination(pai_labeled(p1));
-                Dec(hp^.lab^.refcount);
-                If (hp^.lab^.refcount = 0) Then
-                  hp^.lab^.is_used := False;
-                hp^.lab := pai_labeled(p1)^.lab;
-                Inc(hp^.lab^.refcount);
-              End
-        End
-    End;
-
-    Function IsGP32Reg(Reg: TRegister): Boolean;
-    {Checks if the register is a 32 bit general purpose register}
-    Begin
-      If (Reg >= R_EAX) and (Reg <= R_EBX)
-        Then IsGP32Reg := True
-        Else IsGP32reg := False
-    End;
-
-  begin
-    p:=pai(asml^.first);
-    RegsUsed := [];
-    while assigned(p) do
-       begin
-         Case p^.typ Of
-           ait_labeled_instruction:
-             begin
-  {the following if-block removes all code between a jmp and the next label,
-   because it can never be executed}
-               If (pai_labeled(p)^._operator = A_JMP) Then
-                 Begin
-                   hp1 := pai(p^.next);
-                   While Assigned(hp1) and (hp1^.typ <> ait_label) Do
-                     Begin
-                       AsmL^.Remove(hp1);
-                       Dispose(hp1, done);
-                       hp1 := pai(p^.next);
-                     End;
-                  End;
-               if GetNextInstruction(p, hp1) then
-                 begin
-{                   hp2 := pai(p^.next^.next);}
-                   if (pai(hp1)^.typ=ait_labeled_instruction) and
-                      (pai_labeled(hp1)^._operator=A_JMP) and
-                      GetNextInstruction(hp1, hp2) And
-                      FindLabel(pai_labeled(p)^.lab, hp2)
-                    then
-                      begin
-                        case pai_labeled(p)^._operator of
-                          A_JE : pai_labeled(p)^._operator:=A_JNE;
-                          A_JNE : pai_labeled(p)^._operator:=A_JE;
-                          A_JL : pai_labeled(p)^._operator:=A_JGE;
-                          A_JG : pai_labeled(p)^._operator:=A_JLE;
-                          A_JLE : pai_labeled(p)^._operator:=A_JG;
-                          A_JGE : pai_labeled(p)^._operator:=A_JL;
-                          A_JNZ : pai_labeled(p)^._operator:=A_JZ;
-                          A_JNO : pai_labeled(p)^._operator:=A_JO;
-                          A_JZ : pai_labeled(p)^._operator:=A_JNZ;
-                          A_JS : pai_labeled(p)^._operator:=A_JNS;
-                          A_JNS : pai_labeled(p)^._operator:=A_JS;
-                          A_JO : pai_labeled(p)^._operator:=A_JNO;
-                          A_JC : pai_labeled(p)^._operator:=A_JNC;
-                          A_JNC : pai_labeled(p)^._operator:=A_JC;
-                          A_JA : pai_labeled(p)^._operator:=A_JBE;
-                          A_JAE : pai_labeled(p)^._operator:=A_JB;
-                          A_JB : pai_labeled(p)^._operator:=A_JAE;
-                          A_JBE : pai_labeled(p)^._operator:=A_JA;
-                          else
-                            begin
-                              If (LabDif <> 0) Then GetFinalDestination(pai_labeled(p));
-                              p:=pai(p^.next);
-                              continue;
-                            end;
-                        end;
-                        Dec(pai_label(hp2)^.l^.refcount);
-                        If (pai_label(hp2)^.l^.refcount = 0) Then
-                          Begin
-                            pai_label(hp2)^.l^.is_used := False;
-                            AsmL^.remove(hp2);
-                            Dispose(hp2, done);
-                          End;
-                        pai_labeled(p)^.lab:=pai_labeled(hp1)^.lab;
-                        Inc(pai_labeled(p)^.lab^.refcount);
-{                       hp1:=pai(p^.next);}
-                        asml^.remove(hp1);
-                        dispose(hp1,done);
-                        If (LabDif <> 0) Then GetFinalDestination(pai_labeled(p));
-                      end
-                    else
-                      Begin
-{                        hp2:=pai(p^.next);}
-                        if FindLabel(pai_labeled(p)^.lab, hp1) then
-                          begin
-                            hp2:=pai(hp1^.next);
-                            asml^.remove(p);
-                            dispose(p,done);
-                            If Not(pai_label(hp1)^.l^.is_used) Then
-                              Begin
-                                AsmL^.remove(hp1);
-                                Dispose(hp1, done);
-                              End;
-                            p:=hp2;
-                            continue;
-                          end;
-                        If (LabDif <> 0) Then GetFinalDestination(pai_labeled(p));
-                      end;
-                 end
-             end;
-           ait_instruction:
-             Begin
-               If (Pai386(p)^.op1t = top_ref) Then
-                 With TReference(Pai386(p)^.op1^) Do
-                   Begin
-                     If (base = R_NO) And
-                        (scalefactor = 1)
-                       Then
-                         Begin
-                           base := index;
-                           index := r_no
-                         End
-                    End;
-               If (Pai386(p)^.op2t = top_ref) Then
-                 With TReference(Pai386(p)^.op2^) Do
-                   Begin
-                     If (base = R_NO) And
-                        (scalefactor = 1)
-                       Then
-                         Begin
-                           base := index;
-                           index := r_no
-                         End
-                   End;
-               Case Pai386(p)^._operator Of
-                 A_AND:
-                   Begin
-                     If (Pai386(p)^.op1t = top_const) And
-                        (Pai386(p)^.op2t = top_reg) And
-{                        Assigned(p^.next) And}
-                        GetNextInstruction(p, hp1) And
-                        (Pai(hp1)^.typ = ait_instruction) And
-                        (Pai386(hp1)^._operator = A_AND) And
-                        (Pai386(hp1)^.op1t = top_const) And
-                        (Pai386(hp1)^.op2t = top_reg) And
-                        (Pai386(hp1)^.op2 = Pai386(hp1)^.op2)
-                       Then
-{change "and const1, reg; and const2, reg" to "and (const1 and const2), reg"}
-                         Begin
-                           Pai386(p)^.op1 := Pointer(Longint(Pai386(p)^.op1) And Longint(Pai386(hp1)^.op1));
-{                           hp1 := Pai(p^.next);}
-                           AsmL^.Remove(hp1);
-                           Dispose(hp1, Done)
-                         End;
-                     {
-                     Else
-                       If (Pai386(p)^.op2t = top_reg) And
-                          Assigned(p^.next) And
-                          (Pai(p^.next)^.typ = ait_labeled_instruction)
-                         Then Pai386(p)^._operator := A_TEST;
-                     change "and x, reg; jxx" to "test x, reg
-                     }
-                   End;
-                 A_CMP:
-                   Begin
-                     If (Pai386(p)^.op1t = top_const) And
-                        (Pai386(p)^.op2t = top_reg) And
-                        (Pai386(p)^.op1 = Pointer(0)) Then
-                    {change "cmp $0, %reg" to "test %reg, %reg"}
-                       Begin
-                         Pai386(p)^._operator := A_TEST;
-                         Pai386(p)^.opxt := Top_reg+Top_reg shl 4;
-                         Pai386(p)^.op1 := Pai386(p)^.op2;
-                       End;
-                   End;
-                 A_FSTP:
-                   Begin
-                     If (Pai386(p)^.op1t = top_ref) And
-{                        Assigned(p^.next) And}
-                        GetNextInstruction(p, hp1) And
-                        (Pai(hp1)^.typ = ait_instruction) And
-                        (Pai386(hp1)^._operator = A_FLD) And
-                        (Pai386(hp1)^.op1t = top_ref) And
-                        (Pai386(p)^.Size = Pai386(p)^.Size) And
-                        RefsEqual(TReference(Pai386(p)^.op1^), TReference(Pai386(hp1)^.op1^))
-                       Then
-                         Begin
-{                           hp1 := pai(p^.next^.next);}
-                           If {Assigned(hp1) And}
-                              GetNextInstruction(hp1, hp2) And
-                             (hp2^.typ = ait_instruction) And
-                             ((Pai386(hp2)^._operator = A_LEAVE) Or
-                              (Pai386(hp2)^._operator = A_RET)) And
-                             (TReference(Pai386(p)^.op1^).Base = ProcInfo.FramePointer) And
-                             (TReference(Pai386(p)^.op1^).Offset >= ProcInfo.RetOffset) And
-                             (TReference(Pai386(p)^.op1^).Index = R_NO)
-                            Then
-                              Begin
-{                               hp2 := Pai(p^.next);}
-                                AsmL^.Remove(p);
-                                AsmL^.Remove(hp1);
-                                Dispose(p, Done);
-                                Dispose(hp1, Done);
-                                p := hp2;
-                                Continue
-                              End
-                            Else
-                              Begin
-                                Pai386(p)^._operator := A_FST;
-{                               hp1 := Pai(p^.next);}
-                                AsmL^.Remove(hp1);
-                                Dispose(hp1, done)
-                              End
-                         End;
-                   End;
-                 A_IMUL:
-                   {changes certain "imul const, %reg"'s to lea sequences}
-                   Begin
-                     If (Pai386(p)^.op1t = Top_Const) And
-                       (Pai386(p)^.op2t = Top_Reg) And
-                       (Pai386(p)^.Size = S_L) And
-                       ((Pai386(p)^.op3t = Top_Reg) or
-                        (Pai386(p)^.op3t = Top_None)) And
-                       (aktoptprocessor < PentiumPro) And
-                       (Longint(Pai386(p)^.op1) <= 12) And
-                       Not(CS_LittleSize in AktSwitches) And
-                       (Not(GetNextInstruction(p, hp1)) Or
-                         {GetNextInstruction(p, hp1) And}
-                         Not((Pai(hp1)^.typ = ait_labeled_instruction) And
-                             ((pai_labeled(hp1)^._operator = A_JO) or
-                              (pai_labeled(hp1)^._operator = A_JNO))))
-                      Then
-                        Begin
-                          New(TmpRef);
-                          TmpRef^.segment := R_DEFAULT_SEG;
-                          TmpRef^.symbol := nil;
-                          TmpRef^.isintvalue := false;
-                          TmpRef^.offset := 0;
-                          Case Longint(Pai386(p)^.op1) Of
-                            3: Begin
-                               {imul 3, reg1, reg2 to
-                                  lea (reg1,reg1,2), reg2
-                                imul 3, reg1 to
-                                  lea (reg1,reg1,2), reg1}
-                                 TmpRef^.base := TRegister(Pai386(p)^.op2);
-                                 TmpRef^.Index := TRegister(Pai386(p)^.op2);
-                                 TmpRef^.ScaleFactor := 2;
-                                 If (Pai386(p)^.op3t = Top_None)
-                                   Then hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)))
-                                   Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
-                                    TRegister(twowords(Pai386(p)^.op2).word2)));
-                                 hp1^.fileinfo := p^.fileinfo;
-                                 InsertLLItem(p^.previous, p^.next, hp1);
-                                 Dispose(p, Done);
-                                 p := hp1;
-                              End;
-                           5: Begin
-                              {imul 5, reg1, reg2 to
-                                 lea (reg1,reg1,4), reg2
-                               imul 5, reg1 to
-                                 lea (reg1,reg1,4), reg1}
-                                TmpRef^.base := TRegister(Pai386(p)^.op2);
-                                TmpRef^.Index := TRegister(Pai386(p)^.op2);
-                                TmpRef^.ScaleFactor := 4;
-                                If (Pai386(p)^.op3t = Top_None)
-                                  Then hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)))
-                                  Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
-                                   TRegister(twowords(Pai386(p)^.op2).word2)));
-                                hp1^.fileinfo:= p^.fileinfo;
-                                InsertLLItem(p^.previous, p^.next, hp1);
-                                Dispose(p, Done);
-                                p := hp1;
-                              End;
-                           6: Begin
-                              {imul 6, reg1, reg2 to
-                                 lea (,reg1,2), reg2
-                                 lea (reg2,reg1,4), reg2
-                               imul 6, reg1 to
-                                 lea (reg1,reg1,2), reg1
-                                 add reg1, reg1}
-                                If (aktoptprocessor <= int486)
-                                  Then
-                                    Begin
-                                      TmpRef^.Index := TRegister(Pai386(p)^.op2);
-                                      If (Pai386(p)^.op3t = Top_Reg)
-                                        Then
-                                          Begin
-                                            TmpRef^.base := TRegister(twowords(Pai386(p)^.op2).word2);
-                                            TmpRef^.ScaleFactor := 4;
-                                            hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
-                                              TRegister(twowords(Pai386(p)^.op2).word2)));
-                                          End
-                                        Else
-                                          Begin
-                                            Dispose(TmpRef);
-                                            hp1 :=  New(Pai386, op_reg_reg(A_ADD, S_L,
-                                              TRegister(Pai386(p)^.op2),TRegister(Pai386(p)^.op2)));
-                                          End;
-                                      hp1^.fileinfo := p^.fileinfo;
-                                      InsertLLItem(p, p^.next, hp1);
-                                      New(TmpRef);
-                                      TmpRef^.segment := R_DEFAULT_SEG;
-                                      TmpRef^.symbol := nil;
-                                      TmpRef^.isintvalue := false;
-                                      TmpRef^.offset := 0;
-                                      TmpRef^.Index := TRegister(Pai386(p)^.op2);
-                                      TmpRef^.ScaleFactor := 2;
-                                      If (Pai386(p)^.op3t = Top_Reg)
-                                        Then
-                                          Begin
-                                            TmpRef^.base := R_NO;
-                                            hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
-                                              TRegister(twowords(Pai386(p)^.op2).word2)));
-                                          End
-                                        Else
-                                          Begin
-                                            TmpRef^.base := TRegister(Pai386(p)^.op2);
-                                            hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)));
-                                          End;
-                                      hp1^.fileinfo := p^.fileinfo;
-                                      InsertLLItem(p^.previous, p^.next, hp1);
-                                      Dispose(p, Done);
-                                      p := Pai(hp1^.next);
-                                    End
-                                  Else Dispose(TmpRef);
-                              End;
-                            9: Begin
-                               {imul 9, reg1, reg2 to
-                                  lea (reg1,reg1,8), reg2
-                                imul 9, reg1 to
-                                  lea (reg1,reg1,8), reg1}
-                                 TmpRef^.base := TRegister(Pai386(p)^.op2);
-                                 TmpRef^.Index := TRegister(Pai386(p)^.op2);
-                                 TmpRef^.ScaleFactor := 8;
-                                 If (Pai386(p)^.op3t = Top_None)
-                                     Then hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)))
-                                     Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
-                                      TRegister(twowords(Pai386(p)^.op2).word2)));
-                                   hp1^.fileinfo := p^.fileinfo;
-                                   InsertLLItem(p^.previous, p^.next, hp1);
-                                   Dispose(p, Done);
-                                   p := hp1;
-                                 End;
-                           10: Begin
-                              {imul 10, reg1, reg2 to
-                                 lea (reg1,reg1,4), reg2
-                                 add reg2, reg2
-                               imul 10, reg1 to
-                                 lea (reg1,reg1,4), reg1
-                                 add reg1, reg1}
-                                 If (aktoptprocessor <= int486) Then
-                                   Begin
-                                     If (Pai386(p)^.op3t = Top_Reg)
-                                       Then
-                                         hp1 :=  New(Pai386, op_reg_reg(A_ADD, S_L,
-                                            Tregister(twowords(Pai386(p)^.op2).word2),
-                                            Tregister(twowords(Pai386(p)^.op2).word2)))
-                                       Else hp1 := New(Pai386, op_reg_reg(A_ADD, S_L,
-                                                TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)));
-                                     hp1^.fileinfo := p^.fileinfo;
-                                     InsertLLItem(p, p^.next, hp1);
-                                     TmpRef^.base := TRegister(Pai386(p)^.op2);
-                                     TmpRef^.Index := TRegister(Pai386(p)^.op2);
-                                     TmpRef^.ScaleFactor := 4;
-                                     If (Pai386(p)^.op3t = Top_Reg)
-                                       Then
-                                         hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
-                                            TRegister(twowords(Pai386(p)^.op2).word2)))
-                                       Else
-                                           hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
-                                             TRegister(Pai386(p)^.op2)));
-                                     hp1^.fileinfo := p^.fileinfo;
-                                     InsertLLItem(p^.previous, p^.next, hp1);
-                                     Dispose(p, Done);
-                                     p := Pai(hp1^.next);
-                                   End
-                                 Else Dispose(TmpRef);
-                               End;
-                           12: Begin
-                              {imul 12, reg1, reg2 to
-                                 lea (,reg1,4), reg2
-                                 lea (,reg1,8) reg2
-                               imul 12, reg1 to
-                                 lea (reg1,reg1,2), reg1
-                                 lea (,reg1,4), reg1}
-                                 If (aktoptprocessor <= int486)
-                                   Then
-                                     Begin
-                                       TmpRef^.Index := TRegister(Pai386(p)^.op2);
-                                       If (Pai386(p)^.op3t = Top_Reg)
-                                         Then
-                                           Begin
-                                             TmpRef^.base := TRegister(twowords(Pai386(p)^.op2).word2);
-                                             TmpRef^.ScaleFactor := 8;
-                                             hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
-                                               TRegister(twowords(Pai386(p)^.op2).word2)));
-                                           End
-                                         Else
-                                           Begin
-                                             TmpRef^.base := R_NO;
-                                             TmpRef^.ScaleFactor := 4;
-                                             hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
-                                               TRegister(Pai386(p)^.op2)));
-                                           End;
-                                       hp1^.fileinfo := p^.fileinfo;
-                                       InsertLLItem(p, p^.next, hp1);
-                                       New(TmpRef);
-                                       TmpRef^.segment := R_DEFAULT_SEG;
-                                       TmpRef^.symbol := nil;
-                                       TmpRef^.isintvalue := false;
-                                       TmpRef^.offset := 0;
-                                       TmpRef^.Index := TRegister(Pai386(p)^.op2);
-                                       If (Pai386(p)^.op3t = Top_Reg)
-                                         Then
-                                           Begin
-                                             TmpRef^.base := R_NO;
-                                             TmpRef^.ScaleFactor := 4;
-                                             hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
-                                               TRegister(twowords(Pai386(p)^.op2).word2)));
-                                           End
-                                         Else
-                                           Begin
-                                             TmpRef^.base := TRegister(Pai386(p)^.op2);
-                                             TmpRef^.ScaleFactor := 2;
-                                             hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
-                                               TRegister(Pai386(p)^.op2)));
-                                           End;
-                                       hp1^.fileinfo := p^.fileinfo;
-                                       InsertLLItem(p^.previous, p^.next, hp1);
-                                       Dispose(p, Done);
-                                       p := Pai(hp1^.next);
-                                     End
-                                   Else Dispose(TmpRef);
-                               End
-                            Else Dispose(TmpRef);
-                          End;
-                        End;
-                   End;
-                 A_LEA:
-                   Begin
-                   {changes "lea (%reg1), %reg2" into "mov %reg1, %reg2"}
-                     If (PReference(Pai386(p)^.op1)^.Base >= R_EAX) And
-                        (PReference(Pai386(p)^.op1)^.Base <= R_EDI) And
-                        (PReference(Pai386(p)^.op1)^.Index = R_NO) And
-                        (PReference(Pai386(p)^.op1)^.Offset = 0) And
-                        (Not(Assigned(PReference(Pai386(p)^.op1)^.Symbol))) Then
-                       Begin
-                         hp1 := New(Pai386, op_reg_reg(A_MOV, S_L,PReference(Pai386(p)^.op1)^.Base,
-                           TRegister(Pai386(p)^.op2)));
-                         hp1^.fileinfo := p^.fileinfo;
-                         InsertLLItem(p^.previous,p^.next, hp1);
-                         Dispose(p, Done);
-                         p := hp1;
-                         Continue;
-                       End;
-                   End;
-                 A_MOV:
-                   Begin
-                     If (Pai386(p)^.op2t = top_reg) And
-                        (TRegister(Pai386(p)^.op2) In [{R_EAX, R_EBX, R_EDX, }R_EDI]) And
-{                        Assigned(p^.next) And}
-                        GetNextInstruction(p, hp1) And
-                        (Pai(hp1)^.typ = ait_instruction) And
-                        (Pai386(hp1)^._operator = A_MOV) And
-                        (Pai386(hp1)^.op1t = top_reg) And
-                        (Pai386(hp1)^.op1 = Pai386(p)^.op2)
-                       Then
-                   {we have "mov x, %treg; mov %treg, y}
-                         If (Pai386(hp1)^.op2t <> top_reg) Or
-                            (GetNextInstruction(hp1, hp2) And
-                            RegInInstruction(TRegister(Pai386(hp1)^.op2), hp2))
-                           Then
-                  {we've got "mov x, %treg; mov %treg, y; XXX y" (ie. y is used in
-                   the third instruction)}
-                             Case Pai386(p)^.op1t Of
-                               top_reg:
-                             {change "mov %reg, %treg; mov %treg, y"
-                              to "mov %reg, y"}
-                                 Begin
-                                   Pai386(hp1)^.op1 := Pai386(p)^.op1;
-{                                    hp1 := Pai(p^.next);}
-                                   AsmL^.Remove(p);
-                                   Dispose(p, Done);
-                                   p := hp1;
-                                   continue;
-                                 End;
-                               top_ref:
-                                 If (Pai386(hp1)^.op2t = top_reg)
-                                   Then
-                                {change "mov mem, %treg; mov %treg, %reg"
-                                 to "mov mem, %reg"}
-                                     Begin
-                                       Pai386(p)^.op2 := Pai386(hp1)^.op2;
-{                                       hp1 := Pai(p^.next);}
-                                       AsmL^.Remove(hp1);
-                                       Dispose(hp1, Done);
-                                       continue;
-                                     End;
-                             End
-                           Else
-                  {remove an instruction which never makes sense: we've got
-                   "mov mem, %reg1; mov %reg1, %edi" and then EDI isn't used anymore!}
-                             Begin
-                               If (TRegister(Pai386(hp1)^.op2) = R_EDI) And
-                                  Not({Assigned(p^.next^.next) And}
-                                      GetNextInstruction(hp1, hp2) And
-                                      (Pai(hp2)^.typ = ait_instruction) And
-                                      (Pai386(hp2)^.op2t = top_reg) And
-                                      (Pai386(hp2)^.op2 = Pointer(R_ESI))) Then
-                                 Begin
-{                                  hp1 := pai(p^.next);}
-                                   AsmL^.Remove(hp1);
-                                   Dispose(hp1, Done);
-                                   Continue;
-                                 End
-                             End
-                       Else
-                     {Change "mov %reg1, %reg2; xxx %reg2, ???" to
-                          "mov %reg1, %reg2; xxx %reg1, ???" to
-                          avoid a write/read penalty}
-                         If (Pai386(p)^.op1t = top_reg) And
-                            (Pai386(p)^.op2t = top_reg) And
-{                           Assigned(p^.next) And}
-                            GetNextInstruction(p,hp1) And
-                            (Pai(hp1)^.typ = ait_instruction) And
-                            (Pai386(hp1)^.op1t = top_reg) And
-                            (Pai386(hp1)^.op1 = Pai386(p)^.op2)
-                           Then
-                     {we have "mov %reg1, %reg2; XXX %reg2, ???"}
-                             Begin
-                               If ((Pai386(hp1)^._operator = A_OR) Or
-                                   (Pai386(hp1)^._operator = A_TEST)) And
-                                  (Pai386(hp1)^.op2t = top_reg) And
-                                  (Pai386(hp1)^.op1 = Pai386(hp1)^.op2)
-                                 Then
-                      {we have "mov %reg1, %reg2; test/or %reg2, %reg2"}
-                                   Begin
-                                     If {Assigned(p^.next^.next) And}
-                                        GetNextInstruction(hp1, hp2) And
-                                        (Pai(hp2)^.typ = ait_labeled_instruction) And
-                                        (TRegister(Pai386(p)^.op2) <> R_ESI)
-                                       Then
-                        {change "mov %reg1, %reg2; test/or %reg2, %reg2; jxx" to
-                             "test %reg1, %reg1; jxx"}
-                                         Begin
-{                                          hp1 := pai(p^.next);}
-                                           Pai386(hp1)^.op1 := Pai386(p)^.op1;
-                                           Pai386(hp1)^.op2 := Pai386(p)^.op1;
-                                           AsmL^.Remove(p);
-                                           Dispose(p, done);
-                                           p := hp1;
-                                           continue
-                                         End
-                                       Else
-                         {change "mov %reg1, %reg2; test/or %reg2, %reg2" to
-                          "mov %reg1, %reg2; test/or %reg1, %reg1"}
-                                         Begin
-                                           Pai386(hp1)^.op1 := Pai386(p)^.op1;
-                                           Pai386(hp1)^.op2 := Pai386(p)^.op1;
-                                         End;
-                                   End
-                                 Else
-{                                  If (Pai386(p^.next)^._operator
-                                      In [A_PUSH, A_OR, A_XOR, A_AND, A_TEST])}
-                         {change "mov %reg1, %reg2; push/or/xor/... %reg2, ???" to
-                          "mov %reg1, %reg2; push/or/xor/... %reg1, ???"}
-                             End
-                           Else
-                     {leave out the mov from "mov reg, x(%frame_pointer); leave/ret" (with
-                      x >= RetOffset) as it doesn't do anything (it writes either to a
-                      parameter or to the temporary storage room for the function
-                      result)}
-                             If {Assigned(p^.next) And}
-                                GetNextInstruction(p, hp1) And
-                                (Pai(hp1)^.typ = ait_instruction)
-                               Then
-                                 If ((Pai386(hp1)^._operator = A_LEAVE) Or
-                                     (Pai386(hp1)^._operator = A_RET)) And
-                                    (Pai386(p)^.op2t = top_ref) And
-                                    (TReference(Pai386(p)^.op2^).base = ProcInfo.FramePointer) And
-                                    (TReference(Pai386(p)^.op2^).offset >= ProcInfo.RetOffset) And
-                                    (TReference(Pai386(p)^.op2^).index = R_NO) And
-                                    (Pai386(p)^.op1t = top_reg)
-                                   Then
-                                     Begin
-{                                     hp1 := Pai(p^.next);}
-                                      AsmL^.Remove(p);
-                                      Dispose(p, done);
-                                      p := hp1;
-                                    End
-                                  Else
-                                    If (Pai386(p)^.op1t = top_reg) And
-                                       (Pai386(p)^.op2t = top_ref) And
-                                       (Pai386(p)^.Size = Pai386(hp1)^.Size) And
-                                       (Pai386(hp1)^._operator = A_CMP) And
-                                       (Pai386(hp1)^.op2t = top_ref) And
-                                       RefsEqual(TReference(Pai386(p)^.op2^),
-                                                 TReference(Pai386(hp1)^.op2^))
-                                      Then
-               {change "mov reg, mem1; cmp x, mem1" to "mov reg, mem1; cmp x, reg1"}
-                                        Begin
-                                          Dispose(PReference(Pai386(hp1)^.op2));
-                                          Pai386(hp1)^.opxt := Pai386(hp1)^.op1t + (top_reg shl 4);
-                                          Pai386(hp1)^.op2 := Pai386(p)^.op1
-                                        End;
-                   { Next instruction is also a MOV ? }
-                     If {assigned(p^.next) and}
-                        GetNextInstruction(p, hp1) And
-                        (pai(hp1)^.typ = ait_instruction) and
-                        (Pai386(hp1)^._operator = A_MOV)
-                       Then
-                         Begin
-                           If (Pai386(hp1)^.op1t = Pai386(p)^.op2t) and
-                              (Pai386(hp1)^.op2t = Pai386(p)^.op1t)
-                             Then
-                               {mov reg1, mem1     or     mov mem1, reg1
-                                mov mem2, reg2            mov reg2, mem2}
-                               Begin
-                                 If (Pai386(hp1)^.op2t = top_ref)
-                                   Then
-                                     TmpBool1 := RefsEqual(TReference(Pai386(hp1)^.op2^), TReference(Pai386(p)^.op1^))
-                                   Else
-                                     TmpBool1 := Pai386(hp1)^.op2 = Pai386(p)^.op1;
-                                 If TmpBool1
-                                   Then
-                               {mov reg1, mem1     or     mov mem1, reg1
-                                mov mem2, reg1            mov reg2, mem1}
-                                     Begin
-                                       If (Pai386(hp1)^.op1t = top_ref)
-                                         Then
-                                           TmpBool1 := RefsEqual(TReference(Pai386(hp1)^.op1^),
-                                                                 TReference(Pai386(p)^.op2^))
-                                         Else TmpBool1 := (Pai386(hp1)^.op1 = Pai386(p)^.op2);
-                                      If TmpBool1 Then
-                           { Removes the second statement from
-                               mov reg1, mem1
-                               mov mem1, reg1 }
-                                         Begin
-{                                          hp1 := pai(p^.next);}
-                                           AsmL^.remove(hp1);
-                                           Dispose(hp1,done);
-                                         End;
-                                     End
-                                   Else
-                                     Begin
-{                                      hp1 := pai(p^.next^.next);}
-                                       If GetNextInstruction(hp1, hp2) And
-                                          (Pai386(p)^.op1t = top_ref) And
-                                          (Pai386(p)^.op2t = top_reg) And
-                                          (Pai386(hp1)^.op1t = top_reg) And
-                                          (Pai386(hp1)^.op1 = Pai386(p)^.op2) And
-                                          (Pai386(hp1)^.op2t = top_ref) And
-{                                         Assigned(hp1) And}
-                                          (Pai(hp2)^.typ = ait_instruction) And
-                                          (Pai386(hp2)^._operator = A_MOV) And
-                                          (Pai386(hp2)^.op2t = top_reg) And
-                                          (Pai386(hp2)^.op1t = top_ref) And
-                                          RefsEqual(TReference(Pai386(hp2)^.op1^),
-                                                    TReference(Pai386(hp1)^.op2^))
-                                         Then
-                                           If (TRegister(Pai386(p)^.op2) = R_EDI)
-                                             Then
-                                    {   mov mem1, reg1
-                                        mov reg1, mem2
-                                        mov mem2, reg2
-                                     to:
-                                        mov mem1, reg2
-                                        mov reg2, mem2}
-                                               Begin
-                                                 Pai386(p)^.op2 := Pai386(hp2)^.op2;
-                                                 Pai386(hp1)^.op1 := Pai386(hp2)^.op2;
-                                                 AsmL^.Remove(hp2);
-                                                 Dispose(hp2,Done);
-                                               End
-                                             Else
-                                    {   mov mem1, reg1
-                                        mov reg1, mem2
-                                        mov mem2, reg2
-                                     to:
-                                        mov mem1, reg1
-                                        mov mem1, reg2
-                                        mov reg1, mem2}
-                                               Begin
-                                                 Pai386(hp1)^.opxt := top_ref + top_reg shl 4;
-                                                 Pai386(hp1)^.op1 := Pai386(hp1)^.op2; {move the treference}
-                                                 TReference(Pai386(hp1)^.op1^) := TReference(Pai386(p)^.op1^);
-                                                 If Assigned(TReference(Pai386(p)^.op1^).Symbol) Then
-                                                   Begin
-                                                     New(TReference(Pai386(hp1)^.op1^).Symbol);
-                                                     TReference(Pai386(hp1)^.op1^).Symbol^ :=
-                                                         TReference(Pai386(p)^.op1^).Symbol^;
-                                                   End;
-                                                 Pai386(hp1)^.op2 := Pai386(hp2)^.op2;
-                                                 Pai386(hp2)^.opxt := top_reg + top_ref shl 4;
-                                                 Pai386(hp2)^.op2 := Pai386(hp2)^.op1;
-                                                 Pai386(hp2)^.op1 := Pai386(p)^.op2;
-                                               End;
-                                     End;
-                               End
-                             Else
-(*                             {   movl [mem1],reg1
-                                movl [mem1],reg2
-                               to:
-                                 movl [mem1],reg1
-                                 movl reg1,reg2 }
-                              If (Pai386(p)^.op1t = top_ref) and
-                                 (Pai386(p)^.op2t = top_reg) and
-                                 (Pai386(hp1)^.op1t = top_ref) and
-                                 (Pai386(hp1)^.op2t = top_reg) and
-                                 (Pai386(p)^.size = Pai386(hp1)^.size) and
-                                 RefsEqual(TReference(Pai386(p)^.op1^),TReference(Pai386(hp1)^.op1^)) and
-                                 (TRegister(Pai386(p)^.op2)<>TReference(Pai386(hp1)^.op1^).base) and
-                                 (TRegister(Pai386(p)^.op2)<>TReference(Pai386(hp1)^.op1^).index) then
-                                Begin
-                                  Dispose(PReference(Pai386(hp1)^.op1));
-                                  Pai386(hp1)^.op1:=Pai386(p)^.op2;
-                                  Pai386(hp1)^.opxt:=Top_reg+Top_reg shl 4;
-                                End
-                             Else*)
-                              {   movl const1,[mem1]
-                                  movl [mem1],reg1
-                               to:
-                                  movl const1,reg1
-                                  movl reg1,[mem1] }
-                               If (Pai386(p)^.op1t = top_const) and
-                                  (Pai386(p)^.op2t = top_ref) and
-                                  (Pai386(hp1)^.op1t = top_ref) and
-                                  (Pai386(hp1)^.op2t = top_reg) and
-                                  (Pai386(p)^.size = Pai386(hp1)^.size) and
-                                  RefsEqual(TReference(Pai386(hp1)^.op1^),TReference(Pai386(p)^.op2^)) then
-                                 Begin
-                                   Pai386(hp1)^.op1:=Pai386(hp1)^.op2;
-                                   Pai386(hp1)^.op2:=Pai386(p)^.op2;
-                                   Pai386(hp1)^.opxt:=Top_reg+Top_ref shl 4;
-                                   Pai386(p)^.op2:=Pai386(hp1)^.op1;
-                                   Pai386(p)^.opxt:=Top_const+(top_reg shl 4);
-                                 End
-                         End;
-                          {changes "mov $0, %reg" into "xor %reg, %reg"}
-                     If (Pai386(p)^.op1t = Top_Const) And
-                        (Pai386(p)^.op1 = Pointer(0)) And
-                        (Pai386(p)^.op2t = Top_Reg)
-                        Then
-                          Begin
-                            Pai386(p)^._operator := A_XOR;
-                            Pai386(p)^.opxt := Top_Reg+Top_reg shl 4;
-                            Pai386(p)^.op1 := Pai386(p)^.op2;
-                          End;
-                   End;
-                 A_MOVZX:
-                   Begin
-                   {removes superfluous And's after movzx's}
-                     If (Pai386(p)^.op2t = top_reg) And
-{                        Assigned(p^.next) And}
-                        GetNextInstruction(p, hp1) And
-                        (Pai(hp1)^.typ = ait_instruction) And
-                        (Pai386(hp1)^._operator = A_AND) And
-                        (Pai386(hp1)^.op1t = top_const) And
-                        (Pai386(hp1)^.op2t = top_reg) And
-                        (Pai386(hp1)^.op2 = Pai386(p)^.op2)
-                       Then
-                         Case Pai386(p)^.Size Of
-                           S_BL, S_BW:
-                             If (Longint(Pai386(hp1)^.op1) = $ff)
-                               Then
-                                 Begin
-{                                  hp1 := Pai(p^.next);}
-                                   AsmL^.Remove(hp1);
-                                   Dispose(hp1, Done);
-                                 End;
-                           S_WL:
-                             If (Longint(Pai386(hp1)^.op1) = $ffff)
-                               Then
-                                 Begin
-{                                  hp1 := Pai(p^.next);}
-                                   AsmL^.Remove(hp1);
-                                   Dispose(hp1, Done);
-                                 End;
-                         End;
-                   {changes some movzx constructs to faster synonims (all examples
-                    are given with eax/ax, but are also valid for other registers)}
-                      If (Pai386(p)^.op2t = top_reg) Then
-                        If (Pai386(p)^.op1t = top_reg)
-                          Then
-                            Case Pai386(p)^.size of
-                              S_BW:
-                                Begin
-                                  If (TRegister(Pai386(p)^.op1) = Reg16ToReg8(TRegister(Pai386(p)^.op2))) And
-                                     Not(CS_LittleSize In AktSwitches)
-                                    Then
-                                      {Change "movzbw %al, %ax" to "andw $0x0ffh, %ax"}
-                                      Begin
-                                        Pai386(p)^._operator := A_AND;
-                                        Pai386(p)^.opxt := top_const+Top_reg shl 4;
-                                        Longint(Pai386(p)^.op1) := $ff;
-                                        Pai386(p)^.Size := S_W
-                                      End
-                                    Else
-                                      If {Assigned(p^.next) And}
-                                         GetNextInstruction(p, hp1) And
-                                        (Pai(hp1)^.typ = ait_instruction) And
-                                        (Pai386(hp1)^._operator = A_AND) And
-                                        (Pai386(hp1)^.op1t = top_const) And
-                                        (Pai386(hp1)^.op2t = top_reg) And
-                                        (Pai386(hp1)^.op2 = Pai386(p)^.op2)
-                                          Then
-                                            {Change "movzbw %reg1, %reg2; andw $const, %reg2"
-                                             to "movw %reg1, reg2; andw $(const1 and $ff), %reg2"}
-                                            Begin
-                                              Pai386(p)^._operator := A_MOV;
-                                              Pai386(p)^.Size := S_W;
-                                              Pai386(p)^.op1 := Pointer(Reg8ToReg16(TRegister(Pai386(p)^.op1)));
-                                              Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ff);
-                                            End;
-                                End;
-                              S_BL:
-                                Begin
-                                  If (TRegister(Pai386(p)^.op1) = Reg32ToReg8(TRegister(Pai386(p)^.op2))) And
-                                     Not(CS_LittleSize in AktSwitches)
-                                    Then
-                                      {Change "movzbl %al, %eax" to "andl $0x0ffh, %eax"}
-                                      Begin
-                                        Pai386(p)^._operator := A_AND;
-                                        Pai386(p)^.opxt := top_const+Top_reg shl 4;
-                                        Longint(Pai386(p)^.op1) := $ff;
-                                        Pai386(p)^.Size := S_L;
-                                      End
-                                    Else
-                                      If {Assigned(p^.next) And}
-                                        GetNextInstruction(p, hp1) And
-                                        (Pai(hp1)^.typ = ait_instruction) And
-                                        (Pai386(hp1)^._operator = A_AND) And
-                                        (Pai386(hp1)^.op1t = top_const) And
-                                        (Pai386(hp1)^.op2t = top_reg) And
-                                        (Pai386(hp1)^.op2 = Pai386(p)^.op2)
-                                          Then
-                                            {Change "movzbl %reg1, %reg2; andl $const, %reg2"
-                                             to "movl %reg1, reg2; andl $(const1 and $ff), %reg2"}
-                                            Begin
-                                              Pai386(p)^._operator := A_MOV;
-                                              Pai386(p)^.Size := S_L;
-                                              Pai386(p)^.op1 := Pointer(Reg8ToReg32(TRegister(Pai386(p)^.op1)));
-                                              Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ff);
-                                            End
-                                          Else
-                                            If IsGP32Reg(TRegister(Pai386(p)^.op2)) And
-                                               Not(CS_LittleSize in AktSwitches) And
-                                               (aktoptprocessor >= Pentium) And
-                                               (aktoptprocessor < PentiumPro)
-                                              Then
-                                                {Change "movzbl %reg1, %reg2" to
-                                                 "xorl %reg2, %reg2; movb %reg1, %reg2" for Pentium and
-                                                 PentiumMMX}
-                                                Begin
-                                                  hp1 := New(Pai386, op_reg_reg(A_XOR, S_L,
-                                                             TRegister(Pai386(p)^.op2),
-                                                             TRegister(Pai386(p)^.op2)));
-                                                  hp1^.fileinfo := p^.fileinfo;
-                                                  InsertLLItem(p^.previous, p, hp1);
-                                                  Pai386(p)^._operator := A_MOV;
-                                                  Pai386(p)^.size := S_B;
-                                                  Pai386(p)^.op2 :=
-                                                      Pointer(Reg32ToReg8(TRegister(Pai386(p)^.op2)));
-                                                  InsertLLItem(p, p^.next, hp2);
-                                                End;
-                                End;
-                              S_WL:
-                                Begin
-                                  If (TRegister(Pai386(p)^.op1) = Reg32ToReg16(TRegister(Pai386(p)^.op2))) And
-                                     Not(CS_LittleSize In AktSwitches)
-                                    Then
-                                      {Change "movzwl %ax, %eax" to "andl $0x0ffffh, %eax"}
-                                      Begin
-                                        Pai386(p)^._operator := A_AND;
-                                        Pai386(p)^.opxt := top_const+Top_reg shl 4;
-                                        Longint(Pai386(p)^.op1) := $ffff;
-                                        Pai386(p)^.Size := S_L
-                                      End
-                                    Else
-                                      If {Assigned(p^.next) And}
-                                         GetNextInstruction(p, hp1) And
-                                         (Pai(hp1)^.typ = ait_instruction) And
-                                         (Pai386(hp1)^._operator = A_AND) And
-                                         (Pai386(hp1)^.op1t = top_const) And
-                                         (Pai386(hp1)^.op2t = top_reg) And
-                                         (Pai386(hp1)^.op2 = Pai386(p)^.op2)
-                                        Then
-                                           {Change "movzwl %reg1, %reg2; andl $const, %reg2"
-                                            to "movl %reg1, reg2; andl $(const1 and $ffff), %reg2"}
-                                          Begin
-                                            Pai386(p)^._operator := A_MOV;
-                                            Pai386(p)^.Size := S_L;
-                                            Pai386(p)^.op1 := Pointer(Reg16ToReg32(TRegister(Pai386(p)^.op1)));
-                                            Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ffff);
-                                          End;
-                                End;
-                            End
-                          Else
-                            If (Pai386(p)^.op1t = top_ref) Then
-                              Begin
-                                If (PReference(Pai386(p)^.op1)^.base <> TRegister(Pai386(p)^.op2)) And
-                                   (PReference(Pai386(p)^.op1)^.index <> TRegister(Pai386(p)^.op2)) And
-                                   Not(CS_LittleSize in AktSwitches) And
-                                   IsGP32Reg(TRegister(Pai386(p)^.op2)) And
-                                   (aktoptprocessor >= Pentium) And
-                                   (aktoptprocessor < PentiumPro) And
-                                   (Pai386(p)^.Size = S_BL)
-                                  Then
-                                    {changes "movzbl mem, %reg" to "xorl %reg, %reg; movb mem, %reg8" for
-                                     Pentium and PentiumMMX}
-                                    Begin
-                                      hp1 := New(Pai386,op_reg_reg(A_XOR, S_L, TRegister(Pai386(p)^.op2),
-                                        TRegister(Pai386(p)^.op2)));
-                                      hp1^.fileinfo := p^.fileinfo;
-                                      Pai386(p)^._operator := A_MOV;
-                                      Pai386(p)^.size := S_B;
-                                      Pai386(p)^.op2 := Pointer(Reg32ToReg8(TRegister(Pai386(p)^.op2)));
-                                      InsertLLItem(p^.previous, p, hp1);
-                                    End
-                                  Else
-                                    If {Assigned(p^.next) And}
-                                       GetNextInstruction(p, hp1) And
-                                       (Pai(hp1)^.typ = ait_instruction) And
-                                       (Pai386(hp1)^._operator = A_AND) And
-                                       (Pai386(hp1)^.op1t = Top_Const) And
-                                       (Pai386(hp1)^.op2t = Top_Reg) And
-                                       (Pai386(hp1)^.op2 = Pai386(p)^.op2) Then
-                                      Begin
-                                        Pai386(p)^._operator := A_MOV;
-                                        Case Pai386(p)^.Size Of
-                                          S_BL:
-                                            Begin
-                                              Pai386(p)^.Size := S_L;
-                                              Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
-                                                And $ff);
-                                            End;
-                                          S_WL:
-                                            Begin
-                                              Pai386(p)^.Size := S_L;
-                                              Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
-                                                And $ffff);
-                                            End;
-                                          S_BW:
-                                            Begin
-                                              Pai386(p)^.Size := S_W;
-                                              Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
-                                                And $ff);
-                                            End;
-                                        End;
-                                      End;
-                              End;
-                       End;
-                     A_POP:
-                       Begin
-                         if (Pai386(p)^.op1t = top_reg) And
-{                           (assigned(p^.next)) and}
-                            GetNextInstruction(p, hp1) And
-                            (pai(hp1)^.typ=ait_instruction) and
-                            (Pai386(hp1)^._operator=A_PUSH) and
-                            (Pai386(hp1)^.op1t = top_reg) And
-                            (Pai386(hp1)^.op1=Pai386(p)^.op1) then
-                           If (Not(cs_maxoptimieren in aktswitches)) Then
-                              Begin
-                                hp2:=pai(hp1^.next);
-                                asml^.remove(p);
-                                asml^.remove(hp1);
-                                dispose(p,done);
-                                dispose(hp1,done);
-                                p:=hp2;
-                                continue
-                              End
-                            Else
-                              Begin
-                                Pai386(p)^._operator := A_MOV;
-                                Pai386(p)^.op2 := Pai386(p)^.op1;
-                                Pai386(p)^.opxt := top_ref + top_reg shl 4;
-                                New(TmpRef);
-                                TmpRef^.segment := R_DEFAULT_SEG;
-                                TmpRef^.base := R_ESP;
-                                TmpRef^.index := R_NO;
-                                TmpRef^.scalefactor := 1;
-                                TmpRef^.symbol := nil;
-                                TmpRef^.isintvalue := false;
-                                TmpRef^.offset := 0;
-                                Pai386(p)^.op1 := Pointer(TmpRef);
-                                hp1 := Pai(p^.next);
-                                AsmL^.Remove(hp1);
-                                Dispose(hp1, Done)
-                              End
-                       end;
-                     A_PUSH:
-                       Begin
-                         If (Pai386(p)^.size = S_W) And
-                            (Pai386(p)^.op1t = Top_Const) And
-{                           Assigned(p^.next) And}
-                            GetNextInstruction(p, hp1) And
-                            (Pai(hp1)^.typ = ait_instruction) And
-                            (Pai386(hp1)^._operator = A_PUSH) And
-                            (Pai386(hp1)^.op1t = Top_Const) And
-                            (Pai386(hp1)^.size = S_W) Then
-                              Begin
-{                               hp1 := Pai(p^.next);}
-                                Pai386(p)^.Size := S_L;
-                                Pai386(p)^.op1 := Pointer(Longint(Pai386(p)^.op1) shl 16 + Longint(Pai386(hp1)^.op1));
-                                AsmL^.Remove(hp1);
-                                Dispose(hp1, Done)
-                              End;
-                       End;
-                     A_SHL, A_SAL:
-                       Begin
-                         If (Pai386(p)^.op1t = Top_Const) And
-                            (Pai386(p)^.op2t = Top_Reg) And
-                            (Pai386(p)^.Size = S_L) And
-                            (Longint(Pai386(p)^.op1) <= 3)
-                       {Changes "shl const, %reg32; add const/reg, %reg32" to one lea statement}
-                           Then
-                             Begin
-                               TmpBool1 := True; {should we check the next instruction?}
-                               TmpBool2 := False; {have we found an add/sub which could be
-                                                   integrated in the lea?}
-                               New(TmpRef);
-                               TmpRef^.segment := R_DEFAULT_SEG;
-                               TmpRef^.base := R_NO;
-                               TmpRef^.index := TRegister(Pai386(p)^.op2);
-                               TmpRef^.scalefactor := PowerOf2(Longint(Pai386(p)^.op1));
-                               TmpRef^.symbol := nil;
-                               TmpRef^.isintvalue := false;
-                               TmpRef^.offset := 0;
-                               While  TmpBool1 And
-{                                     Assigned(p^.next) And}
-                                      GetNextInstruction(p, hp1) And
-                                      (Pai(hp1)^.typ = ait_instruction) And
-                                      ((Pai386(hp1)^._operator = A_ADD) Or
-                                       (Pai386(hp1)^._operator = A_SUB)) And
-                                      (Pai386(hp1)^.op2t = Top_Reg) And
-                                      (Pai386(hp1)^.op2 = Pai386(p)^.op2) Do
-                                  Begin
-                                    TmpBool1 := False;
-                                    If (Pai386(hp1)^.op1t = Top_Const)
-                                      Then
-                                        Begin
-                                          TmpBool1 := True;
-                                          TmpBool2 := True;
-                                          If Pai386(hp1)^._operator = A_ADD
-                                            Then Inc(TmpRef^.offset, Longint(Pai386(hp1)^.op1))
-                                            Else Dec(TmpRef^.offset, Longint(Pai386(hp1)^.op1));
-{                                         hp1 := Pai(p^.next);}
-                                          AsmL^.Remove(hp1);
-                                          Dispose(hp1, Done);
-                                        End
-                                      Else
-                                        If (Pai386(hp1)^.op1t = Top_Reg) And
-                                           (Pai386(hp1)^._operator = A_ADD) And
-                                           (TmpRef^.base = R_NO) Then
-                                          Begin
-                                            TmpBool1 := True;
-                                            TmpBool2 := True;
-                                            TmpRef^.base := TRegister(Pai386(hp1)^.op1);
-{                                           hp1 := Pai(p^.next);}
-                                            AsmL^.Remove(hp1);
-                                            Dispose(hp1, Done);
-                                          End;
-                                  End;
-                                If TmpBool2 Or
-                                   ((aktoptprocessor < PentiumPro) And
-                                    (Longint(Pai386(p)^.op1) <= 3) And
-                                    Not(CS_LittleSize in AktSwitches))
-                                   Then
-                                     Begin
-                                       If Not(TmpBool2) And
-                                         (Longint(Pai386(p)^.op1) = 1)
-                                         Then
-                                           Begin
-                                             Dispose(TmpRef);
-                                             hp1 := new(Pai386,op_reg_reg(A_ADD,Pai386(p)^.Size,
-                                                        TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)))
-                                           End
-                                         Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
-                                                         TRegister(Pai386(p)^.op2)));
-                                       hp1^.fileinfo := p^.fileinfo;
-                                       InsertLLItem(p^.previous, p^.next, hp1);
-                                       Dispose(p, Done);
-                                       p := hp1;
-                                     End;
-                             End
-                           Else
-                             If (aktoptprocessor < PentiumPro) And
-                                (Pai386(p)^.op1t = top_const) And
-                                (Pai386(p)^.op2t = top_reg) Then
-                               If (Longint(Pai386(p)^.op1) = 1)
-                                 Then
-                           {changes "shl $1, %reg" to "add %reg, %reg", which
-                            is the same on a 386, but faster on a 486, and pairable in both U and V
-                            pipes on the Pentium (unlike shl, which is only pairable in the U pipe)}
-                                   Begin
-                                     hp1 := new(Pai386,op_reg_reg(A_ADD,Pai386(p)^.Size,
-                                                TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)));
-                                     hp1^.fileinfo := p^.fileinfo;
-                                     InsertLLItem(p^.previous, p^.next, hp1);
-                                     Dispose(p, done);
-                                     p := hp1;
-                                   End
-                                 Else If (Pai386(p)^.size = S_L) and
-                                         (Longint(Pai386(p)^.op1) <= 3) Then
-                           {changes "shl $2, %reg" to "lea (,%reg,4), %reg"
-                                    "shl $3, %reg" to "lea (,%reg,8), %reg}
-                                          Begin
-                                            New(TmpRef);
-                                            TmpRef^.segment := R_DEFAULT_SEG;
-                                            TmpRef^.base := R_NO;
-                                            TmpRef^.index := TRegister(Pai386(p)^.op2);
-                                            TmpRef^.scalefactor := PowerOf2(Longint(Pai386(p)^.op1));
-                                            TmpRef^.symbol := nil;
-                                            TmpRef^.isintvalue := false;
-                                            TmpRef^.offset := 0;
-                                            hp1 := new(Pai386,op_ref_reg(A_LEA,S_L,TmpRef, TRegister(Pai386(p)^.op2)));
-                                            hp1^.fileinfo := p^.fileinfo;
-                                            InsertLLItem(p^.previous, p^.next, hp1);
-                                            Dispose(p, done);
-                                            p := hp1;
-                                          End
-                        End;
-                     A_SAR, A_SHR:
-                         {changes the code sequence
-                          shr/sar const1, %reg
-                          shl     const2, %reg
-                          to either "sar/and", "shl/and" or just "and" depending on const1 and const2}
-                       Begin
-{                        hp1 := pai(p^.next);}
-                         If {Assigned(hp1) and}
-                            GetNextInstruction(p, hp1) And
-                            (pai(hp1)^.typ = ait_instruction) and
-                            (Pai386(hp1)^._operator = A_SHL) and
-                            (Pai386(p)^.op1t = top_const) and
-                            (Pai386(hp1)^.op1t = top_const) Then
-                              If (Longint(Pai386(p)^.op1) > Longint(Pai386(hp1)^.op1)) Then
-                                If (Pai386(p)^.op2t = Top_reg) And
-                                   Not(CS_LittleSize In AktSwitches) And
-                                   ((Pai386(p)^.Size = S_B) Or
-                                    (Pai386(p)^.Size = S_L))
-                                    Then
-                                      Begin
-                                        Dec(Longint(Pai386(p)^.op1), Longint(Pai386(hp1)^.op1));
-                                        Pai386(hp1)^._operator := A_And;
-                                        Pai386(hp1)^.op1 := Pointer(PowerOf2(Longint(Pai386(hp1)^.op1))-1);
-                                        If (Pai386(p)^.Size = S_L)
-                                          Then Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffffffff)
-                                          Else Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
-                                      End
-                                    Else
-                                      If (Longint(Pai386(p)^.op1) < Longint(Pai386(hp1)^.op1)) Then
-                                        If (Pai386(p)^.op2t = Top_reg) And
-                                          Not(CS_LittleSize In AktSwitches) And
-                                          ((Pai386(p)^.Size = S_B) Or
-                                           (Pai386(p)^.Size = S_L))
-                                           Then
-                                             Begin
-                                               Dec(Longint(Pai386(hp1)^.op1), Longint(Pai386(p)^.op1));
-                                               Pai386(p)^._operator := A_And;
-                                               Pai386(p)^.op1 := Pointer(PowerOf2(Longint(Pai386(p)^.op1))-1);
-                                               If (Pai386(p)^.Size = S_L)
-                                                 Then Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffffffff)
-                                                 Else Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
-                                             End
-                                           Else
-                                             Begin
-                                               Pai386(p)^._operator := A_And;
-                                               Pai386(p)^.op1 := Pointer(PowerOf2(Longint(Pai386(p)^.op1))-1);
-                                               Case Pai386(p)^.Size Of
-                                                 S_B: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
-                                                 S_W: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffff);
-                                                 S_L: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor
-                                                   $ffffffff);
-                                               End;
-                                               AsmL^.remove(hp1);
-                                               dispose(hp1, done);
-                                             End;
-                   End;
-                 A_SUB:
-                   {change "subl $2, %esp; pushw x" to "pushl x"}
-                   Begin
-                     If (Pai386(p)^.op1t = top_const) And
-                        (Longint(Pai386(p)^.op1) = 2) And
-                        (Pai386(p)^.op2t = top_reg) And
-                        (TRegister(Pai386(p)^.op2) = R_ESP)
-                       Then
-                         Begin
-                           hp1 := Pai(p^.next);
-                           While Assigned(hp1) And
-                                 (Pai(hp1)^.typ In [ait_instruction]+SkipInstr) And
-                                  Not((Pai(hp1)^.typ = ait_instruction) And
-                                      ((Pai386(hp1)^._operator = A_PUSH) or
-                                       ((Pai386(hp1)^._operator = A_MOV) And
-                                        (Pai386(hp1)^.op2t = top_ref) And
-                                        (TReference(Pai386(hp1)^.op2^).base = r_esp)))) do
-                             hp1 := Pai(hp1^.next);
-                           If Assigned(hp1) And
-                               (Pai(hp1)^.typ = ait_instruction) And
-                               (Pai386(hp1)^._operator = A_PUSH) And
-                               (Pai386(hp1)^.Size = S_W)
-                             Then
-                               Begin
-                                 Pai386(hp1)^.size := S_L;
-                                 If (Pai386(hp1)^.op1t = top_reg) Then
-                                   Pai386(hp1)^.op1 := Pointer(Reg16ToReg32(TRegister(Pai386(hp1)^.op1)));
-                                 hp1 := Pai(p^.next);
-                                 AsmL^.Remove(p);
-                                 Dispose(p, Done);
-                                 p := hp1;
-                                 Continue
-                               End
-                             Else
-                               If {Assigned(p^.previous) And}
-                                  GetLastInstruction(p, hp1) And
-                                  (Pai(hp1)^.typ = ait_instruction) And
-                                  (Pai386(hp1)^._operator = A_SUB) And
-                                  (Pai386(hp1)^.op1t = top_const) And
-                                  (Pai386(hp1)^.op2t = top_reg) And
-                                  (TRegister(Pai386(hp1)^.Op2) = R_ESP)
-                                 Then
-                                   Begin
-{                                   hp1 := Pai(p^.previous);}
-                                    Inc(Longint(Pai386(p)^.op1), Longint(Pai386(hp1)^.op1));
-                                    AsmL^.Remove(hp1);
-                                    Dispose(hp1, Done);
-                                  End;
-                         End;
-                   End;
-                 A_TEST, A_OR:
-                   {removes the line marked with (x) from the sequence
-                    And/or/xor/add/sub/... $x, %y
-                    test/or %y, %y   (x)
-                    j(n)z _Label
-
-                    as the first instruction already adjusts the ZF}
-                    Begin
-                      If (Pai386(p)^.op1 = Pai386(p)^.op2) And
-{                        (assigned(p^.previous)) And}
-                         GetLastInstruction(p, hp1) And
-                         (pai(hp1)^.typ = ait_instruction) Then
-                         Case Pai386(hp1)^._operator Of
-                           A_ADD, A_SUB, A_OR, A_XOR, A_AND, A_SHL, A_SHR:
-                             Begin
-                               If (Pai386(hp1)^.op2 = Pai386(p)^.op1) Then
-                                 Begin
-                                   hp1 := pai(p^.next);
-                                   asml^.remove(p);
-                                   dispose(p, done);
-                                   p := pai(hp1);
-                                   continue
-                                 End;
-                             End;
-                           A_DEC, A_INC, A_NEG:
-                             Begin
-                               If (Pai386(hp1)^.op1 = Pai386(p)^.op1) Then
-                                 Begin
-                                   hp1 := pai(p^.next);
-                                   asml^.remove(p);
-                                   dispose(p, done);
-                                   p := pai(hp1);
-                                   continue
-                                 End;
-                             End
-                         End;
-                    End;
-               End;
-             End;
-           ait_label:
-             Begin
-               If Not(Pai_Label(p)^.l^.is_used)
-                 Then
-                   Begin
-                     hp1 := Pai(p^.next);
-                     AsmL^.Remove(p);
-                     Dispose(p, Done);
-                     p := hp1;
-                     Continue
-                   End;
-             End;
-{$ifdef regalloc}
-           ait_regalloc: UsedRegs := UsedRegs + [PaiAlloc(p)^.Reg];
-           ait_regdealloc: UsedRegs := UsedRegs - [PaiAlloc(p)^.Reg];
-{$endif regalloc}
-         End;
-         p:=pai(p^.next);
-       end;
-end;
-
-
-  Procedure peepholeopt(AsmL : paasmoutput);
-
-    Procedure FindLoHiLabels;
-    {Walks through the paasmlist to find the lowest and highest label number;
-     Since 0.9.3: also removes unused labels}
-    Var LabelFound: Boolean;
-        P, hp1: Pai;
-    Begin
-      LabelFound := False;
-      LoLab := MaxLongint;
-      HiLab := 0;
-      p := Pai(AsmL^.first);
-      While Assigned(p) 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^.nb < LoLab) Then
-                  LoLab := Pai_Label(p)^.l^.nb;
-                  If (Pai_Label(p)^.l^.nb > HiLab) Then
-                  HiLab := Pai_Label(p)^.l^.nb;
-                End
-              Else
-                Begin
-                  hp1 := pai(p^.next);
-                  AsmL^.Remove(p);
-                  Dispose(p, Done);
-                  p := hp1;
-                  continue;
-                End;
-          p := pai(p^.next);
-        End;
-      If LabelFound
-        Then LabDif := HiLab+1-LoLab
-        Else LabDif := 0;
-    End;
-
-    Procedure BuildLabelTable;
-    {Builds a table with the locations of the labels in the paasmoutput}
-    Var p: Pai;
-    Begin
-      If (LabDif <> 0) Then
-        Begin
-{$IfDef TP}
-          If (MaxAvail >= LabDif*SizeOf(Pai))
-            Then
-              Begin
-{$EndIf TP}
-                GetMem(LTable, LabDif*SizeOf(Pai));
-                FillChar(LTable^, LabDif*SizeOf(Pai), 0);
-                p := pai(AsmL^.first);
-                While Assigned(p) Do
-                  Begin
-                    If (Pai(p)^.typ = ait_label) Then
-                      LTable^[Pai_Label(p)^.l^.nb-LoLab] := p;
-                    p := pai(p^.next);
-                  End;
-{$IfDef TP}
-              End
-            Else LabDif := 0;
-{$EndIf TP}
-        End;
-    End;
-
-  Begin
-    FindLoHiLabels;
-    BuildLabelTable;
-    DoOptimize(AsmL);
-    DoOptimize(AsmL);
-    If LabDif <> 0 Then Freemem(LTable, LabDif*SizeOf(Pai));
-    ReloadOpt(AsmL)
-  End;
-
 End.
-{
-  $Log$
-  Revision 1.17  1998-07-15 16:06:00  jonas
-    * change "pop reg/push reg to "mov (%esp), reg" with -Ox, remove otherwise
-
-  Revision 1.16  1998/07/14 14:46:42  peter
-    * released NEWINPUT
-
-  Revision 1.15  1998/06/16 08:56:17  peter
-    + targetcpu
-    * cleaner pmodules for newppu
-
-  Revision 1.14  1998/05/30 14:31:02  peter
-    + $ASMMODE
-
-  Revision 1.13  1998/05/24 18:42:37  jonas
-    * final bugfilx for mov optimizes, remake3 with optimizations works again!
-
-  Revision 1.12  1998/05/24 15:20:59  jonas
-    * 2 bugs fixed in mov peepholeoptimizes
-
-  Revision 1.11  1998/05/23 01:21:00  peter
-    + aktasmmode, aktoptprocessor, aktoutputformat
-    + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
-    + $LIBNAME to set the library name where the unit will be put in
-    * splitted cgi386 a bit (codeseg to large for bp7)
-    * nasm, tasm works again. nasm moved to ag386nsm.pas
-
-  Revision 1.10  1998/05/10 12:06:30  jonas
-    * bugfix in a_mov optimizations; completed bugfix of "sub $2,esp;...;movw reg, y(%esp)"
-
-  Revision 1.9  1998/05/06 08:38:34  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.8  1998/04/29 10:33:43  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.7  1998/04/23 21:52:08  florian
-    * fixes of Jonas applied
-
-  Revision 1.6  1998/04/21 11:30:14  peter
-    * fixed $ifdef regalloc
-
-  Revision 1.5  1998/04/16 16:53:56  jonas
-  *** empty log message ***
-
-  Revision 1.4  1998/04/08 19:12:28  jonas
-    * fixed bug where "imul 12,reg" was replaced with a wrong lea sequence
-
-  Revision 1.3  1998/03/29 17:27:58  florian
-    * aopt386 compiles with TP
-    * correct line number is displayed, if a #0 is in the input
-
-  Revision 1.2  1998/03/28 23:09:53  florian
-    * secondin bugfix (m68k and i386)
-    * overflow checking bugfix (m68k and i386) -- pretty useless in
-      secondadd, since everything is done using 32-bit
-    * loading pointer to routines hopefully fixed (m68k)
-    * flags problem with calls to RTL internal routines fixed (still strcmp
-      to fix) (m68k)
-    * #ELSE was still incorrect (didn't take care of the previous level)
-    * problem with filenames in the command line solved
-    * problem with mangledname solved
-    * linking name problem solved (was case insensitive)
-    * double id problem and potential crash solved
-    * stop after first error
-    * and=>test problem removed
-    * correct read for all float types
-    * 2 sigsegv fixes and a cosmetic fix for Internal Error
-    * push/pop is now correct optimized (=> mov (%esp),reg)
-
-  Revision 1.1.1.1  1998/03/25 11:18:12  root
-  * Restored version
-
-  Revision 1.29  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.28  1998/03/19 18:57:05  florian
-    * small fixes applied
-
-  Revision 1.27  1998/03/18 22:50:10  florian
-    + fstp/fld optimization
-    * routines which contains asm aren't longer optimzed
-    * wrong ifdef TEST_FUNCRET corrected
-    * wrong data generation for array[0..n] of char = '01234'; fixed
-    * bug0097 is fixed partial
-    * bug0116 fixed (-Og doesn't use enter of the stack frame is greater than
-      65535)
-
-  Revision 1.26  1998/03/10 23:48:35  florian
-    * a couple of bug fixes to get the compiler with -OGaxz compiler, sadly
-      enough, it doesn't run
-
-  Revision 1.25  1998/03/10 01:17:14  peter
-    * all files have the same header
-    * messages are fully implemented, EXTDEBUG uses Comment()
-    + AG... files for the Assembler generation
-
-  Revision 1.24  1998/03/04 19:09:59  jonas
-    * fixed incompatibility with new code generator concerning "mov mem, reg; mov reg, edi" optimization
-
-  Revision 1.23  1998/03/03 22:37:09  peter
-    - uses errors
-
-  Revision 1.22  1998/03/03 14:48:31  jonas
-    * added errors to the uses clause (required for aopt386.inc)
-
-  Revision 1.21  1998/03/02 21:35:15  jonas
-    * added comments from last update
-
-  Revision 1.20  1998/03/02 21:29:04  jonas
-   * change "mov reg, mem; cmp x, mem" to "mov reg, mem; cmp x, reg"
-   * change "and x, reg; jxx" to "test reg, x; jxx" (also allows some extra reloading opts)
-
-
-  Revision 1.19  1998/03/02 01:47:58  peter
-    * renamed target_DOS to target_GO32V1
-    + new verbose system, merged old errors and verbose units into one new
-      verbose.pas, so errors.pas is obsolete
-
-  Revision 1.18  1998/02/27 16:33:26  florian
-    * syntax errors and line too long errors fixed
-
-  Revision 1.17  1998/02/26 17:20:31  jonas
-    * re-enabled mov optimizations, re-commented out the "mov mem, reg1; mov mem, reg2" optimization
-
-  Revision 1.16  1998/02/26 11:56:55  daniel
-  * New assembler optimizations commented out, because of bugs.
-  * Use of dir-/name- and extstr.
-
-  Revision 1.15  1998/02/25 14:08:30  daniel
-  * Compiler uses less memory. *FIX*
-
-  Revision 1.14  1998/02/25 12:32:12  daniel
-  * Compiler uses even less memory.
-
-  Revision 1.13  1998/02/24 21:18:12  jonas
-    * file name back to lower case
-
-  Revision 1.2  1998/02/24 20:32:11  jonas
-    * added comments from latest commit
-
-  Revision 1.1  1998/02/24 20:27:50  jonas
-    + change "cmp $0, reg" to "test reg, reg"
-    + add correct line numbers to Pai386 objects created by the optimizer
-    * dispose TReference of second instructions optimized from "mov mem, reg1; mov
-     mem, reg2" to "mov mem, reg; mov reg1, reg2"
-    + optimize "mov mem, reg1; mov reg1, reg2" to "mov mem, reg2" if reg1 <> esi
-    - disabled changing "mov mem, reg1; mov mem reg2" to "mov mem reg1; mov reg1,
-     reg2" because of conflict with the above optimization
-    + remove second instruction from "mov mem, reg; mov reg, %edi" because edi isn't
-     used anymore afterwards
-    + remove first instruction from "mov %eax, x(%ebp); leave/ret" because it is a
-     write to either a parameter or a temporary function result
-    + change "mov reg1, reg2; mov reg2, mem" to "mov reg1, mem" if reg2 <> esi
-    + change "mov reg1, reg2; test/or reg2, reg2; jxx" to "test/or reg1, reg1" if
-     reg2 <> esi
-    + change "mov reg1, reg2; test/or reg2, reg2" to "mov reg1, reg2; test/or reg1,
-     reg1" to avoid a read/write pnealty if reg2 = esi
-    * took FindLoHiLabel and BuildLabelTable out of the main loop, so they're both
-     called only once per code fragment that has to be optimized
-
-  Revision 1.12  1998/02/19 22:46:55  peter
-    * Fixed linebreaks
-
-  Revision 1.11  1998/02/13 10:34:32  daniel
-  * Made Motorola version compilable.
-  * Fixed optimizer
-
-  Revision 1.10  1998/02/12 17:18:51  florian
-    * fixed to get remake3 work, but needs additional fixes (output, I don't like
-      also that aktswitches isn't a pointer)
-
-  Revision 1.9  1998/02/12 11:49:39  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.8  1998/02/10 21:57:21  peter
-    + mov [mem1],reg1;mov [mem1],reg2 -> mov [mem1],reg1;mov reg1,reg2
-    + mov const,[mem1];mov [mem1],reg -> mov const,reg;mov reg,[mem1]
-
-  Revision 1.7  1998/02/07 10:10:34  michael
-    + superfluous AND's after MOVZX' removed
-    + change "subl $2, %esp; ... ; pushw x" to "pushl x"
-    + fold "subl $const, %esp; subl $2, %esp" into one instruction
-
-  Revision 1.5  1998/02/02 17:25:43  jonas
-    * back to CVS version; change "lea (reg1), reg2" to "mov reg1, reg2"
-
-
-  Revision 1.2  1997/12/09 13:19:36  carl
-  + renamed pai_labeled --> pai_labeled
-
-  Revision 1.1.1.1  1997/11/27 08:32:50  michael
-  FPC Compiler CVS start
-
-  Pre-CVS log:
-
-  FK   Florian Klampfl (FK)
-  JM   Jonas Maebe
-
-  + feature added
-  - removed
-  * bug fixed or changed
-
-  History (started with version 0.9.0):
-       5th november 1996:
-         * adapted to 0.9.0
-      30th december 1996:
-         * runs with 0.9.1
-      25th July 1996:
-         + removal of superfluous "test %reg, %reg" instructions (JM)
-      28th July 1997:
-         + change "shl $1, %reg" to "add %reg, %reg" (not working) (JM)
-         * fixed bugs in test optimization (tested and working) (JM)
-      29th July 1997:
-         * fixed some pointer bugs in SHL optimization, but it still doesn't
-           work :( (JM)
-      30th July 1997:
-         + change "sar const1, %reg; shl const2, %reg" to one statement (JM)
-         * I finally correctly understand the structure of the pai(386)
-           object <g> and fixed the shl optimization (tested and working) (JM)
-      31th July 1997:
-         + removal of some superfluous reloading of registers (not working) (JM)
-       4th August 1997:
-         * fixed reloading optimization (thanks Florian!) (JM)
-       6th August 1997:
-         + removal of labels which are not referenced by any instruction
-           (allows for easier and better optimization), but it is slow :( (JM)
-       8th August 1997:
-         - removed label-removal procedure as it seems to be impossible to
-           find out if there are labels which are referenced through a jump
-           table (JM)
-      15th August 1997:
-         + removal of superfluous "or %reg, %reg" instructions (JM)
-      22th september 1997:
-         * test is also removed if it follows neg, shl and shr (FK)
-         - removed the sar/shl optimization because:
-             movl $0xff,%eax
-             shrl $0x3,%eax
-             shll $0x3,%eax
-
-               => EAX is $0xf8  !!!   (FK)
-      23th September 1997:
-         + function FindLabel() so sequences like "jmp l2;l1:;l2:" can be
-           optimized (JM)
-      24th September 1997:
-         + successive jumps reduced to one jump (see explanation at
-           GetFinalDestination). Works fine, but seems to enlarge the code...
-           I suppose because there are more >128 bytes-jumps and their opcodes
-           are longer. If (cs_littlesize in aktwitches^), this optimization is
-           not performed (JM)
-      26th September 1997:
-         * removed the "Var" in front of the parameters of InsertLLItem, which
-           had introduced the need for the temp var p1 (also removed) (JM)
-         * fixed a bug in FindLabel() that caused false positives in some
-           cases (JM)
-         * removed the unit systems from the uses clause because it isn't
-           needed anymore (it was needed for the label-removal procedure) (JM)
-         * adapted for 0.9.3 and 0.9.4 (still bugged) (JM)
-      27th September 1997:
-         * fixed 0.9.3+ related bugs (JM)
-         * make peepholeopt optimize the code twice, because after the first
-           pass several labels can be removed (those unset by
-           GetFinalDestination) which sometimes allows extra optimizations
-           (not when (cs_littlesize in aktswitches^), because then
-           GetFinalDestination is never called)) (JM)
-       1st October 1997:
-         * adapted to use with tp (tlabeltable too large and lines to long) (FK)
-         + removal of dead code (which sits between a jmp and the next label), also
-           sometimes allows some extra optimizations during the second pass (JM)
-       2nd October 1997:
-         + successive conditional jumps reduced to one jump (JM)
-        3rd October 1997:
-         * made FindLabel a little shorter&faster (JM)
-         * make peepholeopt always go through the code twice, because the dead
-           code removal can allow some extra optimizations (JM)
-       10th October 1997:
-         * optimized remove_mov code a little (JM)
-       12th October 1997:
-         * bugfixed remove_mov change (JM)
-       20th October 1997:
-         * changed the combiTmpBoolnation of two adds (which replaced "shl 2, %reg")
-           to a "lea %reg, (,%reg,4)" if the register is 32 bit (JM)
-       21th October 1997:
-         + change movzx to faster equivalents (not working) (thanks to Daniel
-           Mantoine for the initial idea) (JM)
-       30th October 1997:
-         * found out that "shl $const, %reg" is a pairable instruction after
-           all and therefore removed the dual "add %reg, %reg" sequences (JM)
-         * replace "shl $3, %reg" with "lea %reg, (,%reg,8)" (JM)
-        2nd November 1997:
-         * fixed movzx replacements (JM)
-        3rd November 1997:
-         * some changes in the optimization logic to generate better PPro
-           code (JM)
-         * change two consecutive 16 bit immediatie pushes to one 32 bit push
-           (thanks to Synopsis for the suggestion) (JM)
-        4th November 1997:
-         + replace some constant multiplies with lea sequences (suggestion from
-           Synopsis, Daniel Mantoine and Florian Klaempfl) (JM)
-        5th November 1997:
-         * finally bugfixed sar/shl optimization and reactivated it (JM)
-         + some extra movzx optimizations (JM)
-        6th November 1997:
-         + change shl/add/sub sequences to one lea instruction if possible (JM)
-         * bugfixed some imul replacements (JM)
-       30th November 1997:
-         * merge two consecutive "and $const, %reg"'s to one statement (JM)
-        5th December 1997:
-         + change "mov $0, %reg" to "xor %reg, %reg" (JM)
-         * adapted to TP (typecasted pointer to longint for comparisons
-           and one line too long) (JM)
+{
+ $log$
 }
-

+ 397 - 0
compiler/csopt386.pas

@@ -0,0 +1,397 @@
+{
+    $Id$
+    Copyright (c) 1997-98 by Jonas Maebe
+
+    This unit contains the common subexpression elimination procedure.
+
+    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.
+
+ ****************************************************************************
+}
+Unit CSOpt386;
+
+Interface
+
+Uses aasm;
+
+{Procedure CSOpt386(First, Last: Pai);}
+Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
+
+Implementation
+
+Uses CObjects, globals, systems, verbose, hcodegen
+   {$ifdef i386}
+     ,i386, cgi386, DAOpt386
+   {$endif i386}
+     ;
+
+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}
+
+Procedure DoCSE(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;
+              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;
+              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(AsmL: PAasmOutput; 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;
+
+Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
+Begin
+  DoCSE(First, Last);
+  RemoveInstructs(AsmL, First, Last);
+End;
+
+End.
+
+{
+ $log$
+}

+ 1208 - 0
compiler/daopt386.pas

@@ -0,0 +1,1208 @@
+{
+    $Id$
+    Copyright (c) 1997-98 by Jonas Maebe
+
+    This unit contains the data flow analyzer and several helper procedures
+    and functions.
+
+    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.
+
+ ****************************************************************************
+}
+Unit DAOpt386;
+
+Interface
+
+Uses AAsm, CObjects
+  {$ifdef i386}
+    ,i386
+  {$endif}
+  ;
+
+{*********************** Procedures and Functions ************************}
+
+
+Procedure InsertLLItem(AsmL: PAasmOutput; prev, foll, new_one: PLinkedList_Item);
+
+Function Reg32(Reg: TRegister): TRegister;
+Function RefsEqual(Const R1, R2: TReference): Boolean;
+Function IsGP32Reg(Reg: TRegister): Boolean;
+Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
+Function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
+Function PowerOf2(L: Longint): Longint;
+
+Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
+Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
+
+Function RegsSameContent(p1, p2: Pai; Reg: TRegister): Boolean;
+Function InstructionsEqual(p1, p2: Pai): Boolean;
+Procedure DFAPass1(AsmL: PAasmOutput);
+Function DFAPass2(AsmL: PAasmOutput): Pai;
+
+Function FindLabel(L: PLabel; Var hp: Pai): Boolean;
+{Procedure FindLoHiLabels(AsmL: PAasmOutput; Var LoLab, HiLab, LabDif: Longint);}
+
+
+{******************************* Constants *******************************}
+
+Const
+
+{ait_* types which don't result in executable code or which don't influence
+ the way the program runs/behaves}
+
+  SkipInstr = [ait_comment
+{$ifdef GDB}
+  ,ait_stabs, ait_stabn, ait_stab_function_name
+{$endif GDB}
+{$ifdef regalloc}
+  ,ait_regalloc, ait_regdealloc
+{$endif regalloc}
+                     ];
+
+{the maximum number of things (registers, memory, ...) a single instruction
+ changes}
+
+  MaxCh = 3;
+
+{Possible register content types}
+  con_Unknown = 0;
+  con_ref = 1;
+  con_const = 2;
+
+{********************************* Types *********************************}
+
+Type
+
+{What an instruction can change}
+  TChange = (C_None,
+             C_EAX, C_ECX, C_EDX, C_EBX, C_ESP, C_EBP, C_ESI, C_EDI,
+             C_CDirFlag {clear direction flag}, C_SDirFlag {set dir flag},
+             C_Flags, C_FPU, C_Op1, C_Op2, C_Op3, C_MemEDI);
+
+{the possible states of a flag}
+  TFlagContents = (F_Unknown, F_NotSet, F_Set);
+
+{the properties of a cpu instruction}
+  TAsmInstrucProp = Record
+               {how many things it changes}
+                         NCh: Byte;
+               {and what it changes}
+                         Ch: Array[1..MaxCh] of TChange;
+                       End;
+
+  TContent = Record
+      {start and end of block instructions that defines the
+       content of this register. If Typ = con_const, then
+       Longint(StartMod) = value of the constant)}
+               StartMod: Pointer;
+      {starts at 0, gets increased everytime the register is modified}
+               State: Word;
+      {how many instructions starting with StarMod does the block consist of}
+               NrOfMods: Byte;
+      {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)}
+{               ModReg: TRegister; }
+      {the tpye of the content of the register: constant, ...}
+               Typ: Byte;
+             End;
+
+{Contents of the integer registers}
+  TRegContent = Array[R_NO..R_EDI] Of TContent;
+
+{contents of the FPU registers}
+  TRegFPUContent = Array[R_ST..R_ST7] Of TContent;
+
+{information record with the contents of every register. Every Pai object
+ gets one of these assigned: a pointer to it is stored in the Line field and
+ the original line number is stored in LineSave}
+  TPaiProp = Record
+               Regs: TRegContent;
+{               FPURegs: TRegFPUContent;} {currently not yet used}
+               LineSave: Longint;
+    {status of the direction flag}
+               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;
+
+{$IfDef JmpAnal}
+  TLabelTableItem = Record
+                      p: Pai;
+{$IfDef TP}
+                      RefsFound: Byte;
+{$Else TP}
+                      RefsFound: Word;
+{$EndIf TP}
+                      AlreadyProcessed: Boolean;
+                    End;
+{$Else JmpAnal}
+  TLabelTableItem = Pai;
+{$Endif JmpAnal}
+{$IfDef tp}
+  TLabelTable = Array[0..9000] Of TLabelTableItem;
+{$Else tp}
+  TLabelTable = Array[0..2500000] Of TLabelTableItem;
+{$Endif tp}
+  PLabelTable = ^TLabelTable;
+  TwoWords = Record
+               Word1, Word2: Word;
+             End;
+
+{******************************* Variables *******************************}
+
+
+Var
+{the amount of PaiObjects in the current assembler list}
+  NrOfPaiObjs,
+{for TP only: the amount of PPaiProps that can be stored in the PaiPropBlock}
+  NrOfPaiFast: Longint;
+{Array which holds all (FPC) or as much as possible (TP) PPaiProps}
+  PaiPropBlock: PPaiPropBlock;
+
+  LoLab, HiLab, LabDif: Longint;
+
+  LTable: PLabelTable;
+
+{*********************** End of Interface section ************************}
+
+
+Implementation
+
+Uses globals, systems, strings, verbose, hcodegen,
+   {$ifdef i386}
+     cgi386;
+   {$endif i386}
+
+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
+ {How many instructions are betwen the current instruction and the last one
+  that modified the register}
+  NrOfInstrSinceLastMod: Array[R_EAX..R_EDI] Of Byte;
+
+
+{************************ Create the Label table ************************}
+
+Procedure FindLoHiLabels(AsmL: PAasmOutput; Var LoLab, HiLab, LabDif: Longint);
+{Walks through the paasmlist to find the lowest and highest label number;
+ Since 0.9.3: also removes unused labels}
+Var LabelFound: Boolean;
+    P, hp1: Pai;
+Begin
+  LabelFound := False;
+  LoLab := MaxLongint;
+  HiLab := 0;
+  P := Pai(AsmL^.first);
+  While Assigned(p) 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^.nb < LoLab) Then
+                LoLab := Pai_Label(p)^.l^.nb;
+              If (Pai_Label(p)^.l^.nb > HiLab) Then
+                HiLab := Pai_Label(p)^.l^.nb;
+            End
+          Else
+            Begin
+              hp1 := pai(p^.next);
+              AsmL^.Remove(p);
+              Dispose(p, Done);
+              p := hp1;
+              continue;
+            End;
+      p := pai(p^.next);
+    End;
+  If LabelFound
+    Then LabDif := HiLab+1-LoLab
+    Else LabDif := 0;
+End;
+
+Procedure BuildLabelTable(AsmL: PAasmOutput; Var LabelTable: PLabelTable; LowLabel: Longint; Var LabelDif: Longint);
+{Builds a table with the locations of the labels in the paasmoutput}
+Var p: Pai;
+Begin
+  If (LabelDif <> 0) Then
+    Begin
+{$IfDef TP}
+      If (MaxAvail >= LabelDif*SizeOf(Pai))
+        Then
+          Begin
+{$EndIf TP}
+            GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
+            FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
+            p := pai(AsmL^.first);
+            While Assigned(p) Do
+              Begin
+                If (Pai(p)^.typ = ait_label) Then
+{$IfDef JmpAnal}
+                  LabelTable^[Pai_Label(p)^.l^.nb-LowLabel].p := p;
+{$Else JmpAnal}
+                  LabelTable^[Pai_Label(p)^.l^.nb-LowLabel] := p;
+{$EndIf JmpAnal}
+                p := pai(p^.next);
+              End;
+{$IfDef TP}
+          End
+        Else LabelDif := 0;
+{$EndIf TP}
+    End;
+End;
+
+{************************ Search the Label table ************************}
+
+Function FindLabel(L: PLabel; Var hp: Pai): Boolean;
+
+{searches for the specified label starting from hp as long as the
+ encountered instructions are labels, to be able to optimize constructs like
+
+ jne l2              jmp l2
+ jmp l3     and      l1:
+ l1:                 l2:
+ l2:}
+
+Var TempP: Pai;
+
+Begin
+  TempP := hp;
+  While Assigned(TempP) and
+       (pai(TempP)^.typ In SkipInstr + [ait_label]) Do
+    If (pai_label(TempP)^.l <> L)
+      Then TempP := Pai(TempP^.next)
+      Else
+        Begin
+          hp := TempP;
+          FindLabel := True;
+          exit
+        End;
+  FindLabel := False
+End;
+
+{************************ Some general functions ************************}
+
+Function Reg32(Reg: TRegister): TRegister;
+{Returns the 32 bit component of Reg if it exists, otherwise Reg is returned}
+Begin
+  Reg32 := Reg;
+  If (Reg >= R_AX)
+    Then
+      If (Reg <= R_DI)
+        Then Reg32 := Reg16ToReg32(Reg)
+        Else
+          If (Reg <= R_BL)
+            Then Reg32 := Reg8toReg32(Reg);
+End;
+
+Function PowerOf2(L: Longint): Longint;
+Var Counter, TempVal: Longint;
+Begin
+  TempVal := 1;
+  For Counter := 1 to L Do
+    TempVal := TempVal * 2;
+  PowerOf2 := TempVal;
+End;
+
+{ inserts new_one between prev and foll }
+Procedure InsertLLItem(AsmL: PAasmOutput; prev, foll, new_one: PLinkedList_Item);
+Begin
+  If Assigned(prev) Then
+    If Assigned(foll) Then
+      Begin
+        If Assigned(new_one) Then
+          Begin
+            new_one^.previous := prev;
+            new_one^.next := foll;
+            prev^.next := new_one;
+            foll^.previous := new_one;
+          End;
+      End
+    Else AsmL^.Concat(new_one)
+  Else If Assigned(Foll) Then AsmL^.Insert(new_one)
+End;
+
+{********************* Compare parts of Pai objects *********************}
+
+Function RefsEqual(Const R1, R2: TReference): Boolean;
+Begin
+  If R1.IsIntValue
+     Then RefsEqual := R2.IsIntValue and (R1.Offset = R2.Offset)
+     Else If (R1.Offset = R2.Offset) And (R1.Base = R2.Base) And
+             (R1.Index = R2.Index) And (R1.Segment = R2.Segment) And
+             (R1.ScaleFactor = R2.ScaleFactor)
+            Then
+              Begin
+                If Assigned(R1.Symbol)
+                  Then RefsEqual := Assigned(R2.Symbol) And (R1.Symbol^=R2.Symbol^)
+                  Else RefsEqual := Not(Assigned(R2.Symbol));
+              End
+            Else RefsEqual := False;
+End;
+
+Function IsGP32Reg(Reg: TRegister): Boolean;
+{Checks if the register is a 32 bit general purpose register}
+Begin
+  If (Reg >= R_EAX) and (Reg <= R_EBX)
+    Then IsGP32Reg := True
+    Else IsGP32reg := False
+End;
+
+Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
+Begin {checks whether Ref contains a reference to Reg}
+  Reg := Reg32(Reg);
+  RegInRef := (Ref.Base = Reg) Or (Ref.Index = Reg)
+End;
+
+Function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
+{checks if Reg is used by the instruction p1}
+Var TmpResult: Boolean;
+Begin
+  TmpResult := False;
+  If (Pai(p1)^.typ = ait_instruction) Then
+    Begin
+      Case Pai386(p1)^.op1t Of
+        Top_Reg: TmpResult := Reg = TRegister(Pai386(p1)^.op1);
+        Top_Ref: TmpResult := RegInRef(Reg, TReference(Pai386(p1)^.op1^))
+      End;
+      If Not(TmpResult) Then
+        Case Pai386(p1)^.op2t Of
+          Top_Reg:
+              if Pai386(p1)^.op3t<>Top_reg
+                then TmpResult := Reg = TRegister(Pai386(p1)^.op2)
+                else TmpResult := longint(Reg) = twowords(Pai386(p1)^.op2).word1;
+          Top_Ref: TmpResult := RegInRef(Reg, TReference(Pai386(p1)^.op2^))
+        End;
+      If Not(TmpResult) Then
+        Case Pai386(p1)^.op3t Of
+          Top_Reg: TmpResult := longint(Reg) =twowords(Pai386(p1)^.op2).word2;
+          Top_none:;
+          else
+             internalerror($Da);
+       End
+    End;
+  RegInInstruction := TmpResult
+End;
+
+{********************* GetNext and GetLastInstruction *********************}
+
+Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
+{skips ait_regalloc, ait_regdealloc and ait_stab* objects and puts the
+ next pai object in Next. Returns false if there isn't any}
+Begin
+  GetNextInstruction := False;
+  Current := Pai(Current^.Next);
+  While Assigned(Current) And
+        (Pai(Current)^.typ In SkipInstr) Do
+    Current := Pai(Current^.Next);
+  If Assigned(Current)
+    Then
+      Begin
+        Next := Current;
+        GetNextInstruction := True;
+      End;
+End;
+
+Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
+{skips the ait-types in SkipInstr puts the previous pai object in
+ Last. Returns false if there isn't any}
+Begin
+  GetLastInstruction := False;
+  Current := Pai(Current^.previous);
+  While Assigned(Current) And
+        (Pai(Current)^.typ In SkipInstr) Do
+    Current := Pai(Current^.previous);
+  If Assigned(Current)
+    Then
+      Begin
+        Last := Current;
+        GetLastInstruction := True;
+      End;
+End;
+
+{******************* The Data Flow Analyzer functions ********************}
+
+(*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;*)
+
+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 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;
+
+
+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;
+
+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;
+
+Procedure DFAPass1(AsmL: PAasmOutput);
+{gathers the RegAlloc data... still need to think about where to store it}
+Begin
+  FindLoHiLabels(AsmL, LoLab, HiLab, LabDif);
+  BuildLabelTable(AsmL, LTable, LoLab, LabDif);
+End;
+
+Function DoDFAPass2(First: Pai): Pai;
+{Analyzes the Data Flow of an assembler list. 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
+      DoDFAPass2 := 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
+              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);
+                                  If (typ <> Con_Ref) Then
+                                    Begin
+                                      typ := Con_Ref;
+                                      StartMod := p;
+                                    End;
+ {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)^.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;
+              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;
+
+Function InitDFAPass2(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 InitDFAPass2 := False
+    Else
+      Begin
+        InitDFAPass2 := 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}
+  InitDFAPass2 := True;
+  GetMem(PaiPropBlock, NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4));
+  NrOfPaiFast := NrOfPaiObjs;
+ {$EndIf TP}
+End;
+
+Function DFAPass2(AsmL: PAasmOutPut): Pai;
+Begin
+  If InitDFAPass2(AsmL)
+    Then DFAPass2 := DoDFAPass2(Pai(AsmL^.First))
+    Else DFAPass2 := Nil;
+End;
+
+End.

+ 1376 - 0
compiler/popt386.pas

@@ -0,0 +1,1376 @@
+{
+    $Id$
+    Copyright (c) 1993-98 by Floarian Klaempfl and Jonas Maebe
+
+    This unit contains the peephole optimizer.
+
+    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.
+
+ ****************************************************************************
+}
+Unit POpt386;
+
+Interface
+
+Uses Aasm;
+
+Procedure PeepHoleOptPass1(AsmL: PAasmOutput);
+Procedure PeepHoleOptPass2(AsmL: PAasmOutput);
+
+Implementation
+
+Uses CObjects, globals, systems, strings, verbose, hcodegen
+   {$ifdef i386}
+     ,i386, cgi386, DAOpt386
+   {$endif i386}
+     ;
+
+{Procedure PeepHoleOptPass1(AsmL: PAasmOutput);}
+
+Procedure PeepHoleOptPass1(Asml: PAasmOutput);
+{First pass of peepholeoptimizations}
+
+Var
+  p ,hp1, hp2: pai;
+  TmpBool1, TmpBool2: Boolean;
+
+  TmpRef: PReference;
+
+{$Ifdef RegAlloc}
+  RegsUsed: Set of TRegister;
+{$EndIf RegAlloc}
+
+  Procedure GetFinalDestination(hp: pai_labeled);
+  {traces sucessive jumps to their final destination and sets it, e.g.
+   je l1                je l3
+   <code>               <code>
+   l1:       becomes    l1:
+   je l2                je l3
+   <code>               <code>
+   l2:                  l2:
+   jmp l3               jmp l3}
+
+  Var p1: pai;
+
+    Function SkipLabels(hp: Pai): Pai;
+    {skips all labels and returns the next "real" instruction; it is
+     assumed that hp is of the type ait_label}
+    Begin
+      While assigned(hp^.next) and
+            (pai(hp^.next)^.typ In SkipInstr + [ait_label]) Do
+        hp := pai(hp^.next);
+      If assigned(hp^.next)
+        Then SkipLabels := pai(hp^.next)
+        Else SkipLabels := hp;
+    End;
+
+  Begin
+    If (hp^.lab^.nb >= LoLab) and
+       (hp^.lab^.nb <= HiLab) and   {range check, necessary?}
+  {$IfDef JmpAnal}
+       (Pointer(LTable^[hp^.lab^.nb-LoLab].p) <> Pointer(0)) Then
+  {$Else JmpAnal}
+       (Pointer(LTable^[hp^.lab^.nb-LoLab]) <> Pointer(0)) Then
+  {$EndIf JmpAnal}
+      Begin
+  {$IfDef JmpAnal}
+        p1 := LTable^[hp^.lab^.nb-LoLab].p; {the jump's destination}
+  {$Else JmpAnal}
+        p1 := LTable^[hp^.lab^.nb-LoLab]; {the jump's destination}
+  {$EndIf JmpAnal}
+        p1 := SkipLabels(p1);
+        If (pai(p1)^.typ = ait_labeled_instruction) and
+           ((pai_labeled(p1)^._operator = A_JMP) or
+            (pai_labeled(p1)^._operator = hp^._operator))
+          Then
+            Begin
+              GetFinalDestination(pai_labeled(p1));
+              Dec(hp^.lab^.refcount);
+              If (hp^.lab^.refcount = 0) Then
+                hp^.lab^.is_used := False;
+              hp^.lab := pai_labeled(p1)^.lab;
+              Inc(hp^.lab^.refcount);
+            End
+      End
+  End;
+
+Begin
+  P := Pai(AsmL^.First);
+{$IfDef RegAlloc}
+  RegsUsed := [];
+{$EndIf RegAlloc}
+  While Assigned(P) Do
+    Begin
+      Case P^.Typ Of
+        Ait_Labeled_Instruction:
+          Begin
+  {the following if-block removes all code between a jmp and the next label,
+   because it can never be executed}
+            If (pai_labeled(p)^._operator = A_JMP) Then
+              Begin
+                hp1 := pai(p^.next);
+                While Assigned(hp1) and (hp1^.typ <> ait_label) Do
+                  Begin
+                    AsmL^.Remove(hp1);
+                    Dispose(hp1, done);
+                    hp1 := pai(p^.next);
+                  End;
+               End;
+            If GetNextInstruction(p, hp1) then
+              Begin
+                If (pai(hp1)^.typ=ait_labeled_instruction) and
+                   (pai_labeled(hp1)^._operator=A_JMP) and
+                   GetNextInstruction(hp1, hp2) And
+                   FindLabel(pai_labeled(p)^.lab, hp2)
+                  Then
+                    Begin
+                      Case pai_labeled(p)^._operator Of
+                        A_JE : pai_labeled(p)^._operator:=A_JNE;
+                        A_JNE : pai_labeled(p)^._operator:=A_JE;
+                        A_JL : pai_labeled(p)^._operator:=A_JGE;
+                        A_JG : pai_labeled(p)^._operator:=A_JLE;
+                        A_JLE : pai_labeled(p)^._operator:=A_JG;
+                        A_JGE : pai_labeled(p)^._operator:=A_JL;
+                        A_JNZ : pai_labeled(p)^._operator:=A_JZ;
+                        A_JNO : pai_labeled(p)^._operator:=A_JO;
+                        A_JZ : pai_labeled(p)^._operator:=A_JNZ;
+                        A_JS : pai_labeled(p)^._operator:=A_JNS;
+                        A_JNS : pai_labeled(p)^._operator:=A_JS;
+                        A_JO : pai_labeled(p)^._operator:=A_JNO;
+                        A_JC : pai_labeled(p)^._operator:=A_JNC;
+                        A_JNC : pai_labeled(p)^._operator:=A_JC;
+                        A_JA : pai_labeled(p)^._operator:=A_JBE;
+                        A_JAE : pai_labeled(p)^._operator:=A_JB;
+                        A_JB : pai_labeled(p)^._operator:=A_JAE;
+                        A_JBE : pai_labeled(p)^._operator:=A_JA;
+                        Else
+                          begin
+                            If (LabDif <> 0) Then GetFinalDestination(pai_labeled(p));
+                            p:=pai(p^.next);
+                            continue;
+                          end;
+                      end;
+                      Dec(pai_label(hp2)^.l^.refcount);
+                      If (pai_label(hp2)^.l^.refcount = 0) Then
+                        Begin
+                          pai_label(hp2)^.l^.is_used := False;
+                          AsmL^.remove(hp2);
+                          Dispose(hp2, done);
+                        End;
+                      pai_labeled(p)^.lab:=pai_labeled(hp1)^.lab;
+                      Inc(pai_labeled(p)^.lab^.refcount);
+                      asml^.remove(hp1);
+                      dispose(hp1,done);
+                      If (LabDif <> 0) Then GetFinalDestination(pai_labeled(p));
+                    end
+                  else
+                    Begin
+                      if FindLabel(pai_labeled(p)^.lab, hp1) then
+                        begin
+                          hp2:=pai(hp1^.next);
+                          asml^.remove(p);
+                          dispose(p,done);
+                          If Not(pai_label(hp1)^.l^.is_used) Then
+                            Begin
+                              AsmL^.remove(hp1);
+                              Dispose(hp1, done);
+                            End;
+                          p:=hp2;
+                          continue;
+                        end;
+                      If (LabDif <> 0) Then GetFinalDestination(pai_labeled(p));
+                    end;
+              end
+          end;
+        ait_instruction:
+          Begin
+            If (Pai386(p)^.op1t = top_ref) Then
+              With TReference(Pai386(p)^.op1^) Do
+                Begin
+                  If (base = R_NO) And
+                     (scalefactor = 1)
+                    Then
+                      Begin
+                        base := index;
+                        index := r_no
+                      End
+                 End;
+            If (Pai386(p)^.op2t = top_ref) Then
+              With TReference(Pai386(p)^.op2^) Do
+                Begin
+                  If (base = R_NO) And
+                     (scalefactor = 1)
+                    Then
+                      Begin
+                        base := index;
+                        index := r_no
+                      End
+                End;
+            Case Pai386(p)^._operator Of
+              A_AND:
+                Begin
+                  If (Pai386(p)^.op1t = top_const) And
+                     (Pai386(p)^.op2t = top_reg) And
+                     GetNextInstruction(p, hp1) And
+                     (Pai(hp1)^.typ = ait_instruction) And
+                     (Pai386(hp1)^._operator = A_AND) And
+                     (Pai386(hp1)^.op1t = top_const) And
+                     (Pai386(hp1)^.op2t = top_reg) And
+                     (Pai386(hp1)^.op2 = Pai386(hp1)^.op2)
+                    Then
+{change "and const1, reg; and const2, reg" to "and (const1 and const2), reg"}
+                      Begin
+                        Pai386(p)^.op1 := Pointer(Longint(Pai386(p)^.op1) And Longint(Pai386(hp1)^.op1));
+                        AsmL^.Remove(hp1);
+                        Dispose(hp1, Done)
+                      End;
+                  {
+                  Else
+                    If (Pai386(p)^.op2t = top_reg) And
+                       Assigned(p^.next) And
+                       (Pai(p^.next)^.typ = ait_labeled_instruction)
+                      Then Pai386(p)^._operator := A_TEST;
+                  change "and x, reg; jxx" to "test x, reg
+                  }
+                End;
+              A_CMP:
+                Begin
+                  If (Pai386(p)^.op1t = top_const) And
+                     (Pai386(p)^.op2t = top_reg) And
+                     (Pai386(p)^.op1 = Pointer(0)) Then
+                 {change "cmp $0, %reg" to "test %reg, %reg"}
+                    Begin
+                      Pai386(p)^._operator := A_TEST;
+                      Pai386(p)^.opxt := Top_reg+Top_reg shl 4;
+                      Pai386(p)^.op1 := Pai386(p)^.op2;
+                    End;
+                End;
+              A_FSTP:
+                Begin
+                  If (Pai386(p)^.op1t = top_ref) And
+                     GetNextInstruction(p, hp1) And
+                     (Pai(hp1)^.typ = ait_instruction) And
+                     (Pai386(hp1)^._operator = A_FLD) And
+                     (Pai386(hp1)^.op1t = top_ref) And
+                     (Pai386(p)^.Size = Pai386(p)^.Size) And
+                     RefsEqual(TReference(Pai386(p)^.op1^), TReference(Pai386(hp1)^.op1^))
+                    Then
+                      Begin
+                        If GetNextInstruction(hp1, hp2) And
+                           (hp2^.typ = ait_instruction) And
+                           ((Pai386(hp2)^._operator = A_LEAVE) Or
+                            (Pai386(hp2)^._operator = A_RET)) And
+                           (TReference(Pai386(p)^.op1^).Base = ProcInfo.FramePointer) And
+                           (TReference(Pai386(p)^.op1^).Offset >= ProcInfo.RetOffset) And
+                           (TReference(Pai386(p)^.op1^).Index = R_NO)
+                          Then
+                            Begin
+                              AsmL^.Remove(p);
+                              AsmL^.Remove(hp1);
+                              Dispose(p, Done);
+                              Dispose(hp1, Done);
+                              p := hp2;
+                              Continue
+                            End
+                          Else
+                            Begin
+                              Pai386(p)^._operator := A_FST;
+                              AsmL^.Remove(hp1);
+                              Dispose(hp1, done)
+                            End
+                      End;
+                End;
+              A_IMUL:
+                {changes certain "imul const, %reg"'s to lea sequences}
+                Begin
+                  If (Pai386(p)^.op1t = Top_Const) And
+                     (Pai386(p)^.op2t = Top_Reg) And
+                     (Pai386(p)^.Size = S_L) And
+                     ((Pai386(p)^.op3t = Top_Reg) or
+                      (Pai386(p)^.op3t = Top_None)) And
+                     (aktoptprocessor < PentiumPro) And
+                     (Longint(Pai386(p)^.op1) <= 12) And
+                     Not(CS_LittleSize in AktSwitches) And
+                     (Not(GetNextInstruction(p, hp1)) Or
+                       {GetNextInstruction(p, hp1) And}
+                       Not((Pai(hp1)^.typ = ait_labeled_instruction) And
+                           ((pai_labeled(hp1)^._operator = A_JO) or
+                            (pai_labeled(hp1)^._operator = A_JNO))))
+                    Then
+                      Begin
+                        New(TmpRef);
+                        TmpRef^.segment := R_DEFAULT_SEG;
+                        TmpRef^.symbol := nil;
+                        TmpRef^.isintvalue := false;
+                        TmpRef^.offset := 0;
+                        Case Longint(Pai386(p)^.op1) Of
+                          3: Begin
+                             {imul 3, reg1, reg2 to
+                                lea (reg1,reg1,2), reg2
+                              imul 3, reg1 to
+                                lea (reg1,reg1,2), reg1}
+                               TmpRef^.base := TRegister(Pai386(p)^.op2);
+                               TmpRef^.Index := TRegister(Pai386(p)^.op2);
+                               TmpRef^.ScaleFactor := 2;
+                               If (Pai386(p)^.op3t = Top_None)
+                                 Then hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)))
+                                 Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
+                                  TRegister(twowords(Pai386(p)^.op2).word2)));
+                               hp1^.fileinfo := p^.fileinfo;
+                               InsertLLItem(AsmL,p^.previous, p^.next, hp1);
+                               Dispose(p, Done);
+                               p := hp1;
+                            End;
+                         5: Begin
+                            {imul 5, reg1, reg2 to
+                               lea (reg1,reg1,4), reg2
+                             imul 5, reg1 to
+                               lea (reg1,reg1,4), reg1}
+                              TmpRef^.base := TRegister(Pai386(p)^.op2);
+                              TmpRef^.Index := TRegister(Pai386(p)^.op2);
+                              TmpRef^.ScaleFactor := 4;
+                              If (Pai386(p)^.op3t = Top_None)
+                                Then hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)))
+                                Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
+                                 TRegister(twowords(Pai386(p)^.op2).word2)));
+                              hp1^.fileinfo:= p^.fileinfo;
+                              InsertLLItem(AsmL,p^.previous, p^.next, hp1);
+                              Dispose(p, Done);
+                              p := hp1;
+                            End;
+                         6: Begin
+                            {imul 6, reg1, reg2 to
+                               lea (,reg1,2), reg2
+                               lea (reg2,reg1,4), reg2
+                             imul 6, reg1 to
+                               lea (reg1,reg1,2), reg1
+                               add reg1, reg1}
+                              If (aktoptprocessor <= int486)
+                                Then
+                                  Begin
+                                    TmpRef^.Index := TRegister(Pai386(p)^.op2);
+                                    If (Pai386(p)^.op3t = Top_Reg)
+                                      Then
+                                        Begin
+                                          TmpRef^.base := TRegister(twowords(Pai386(p)^.op2).word2);
+                                          TmpRef^.ScaleFactor := 4;
+                                          hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
+                                            TRegister(twowords(Pai386(p)^.op2).word2)));
+                                        End
+                                      Else
+                                        Begin
+                                          Dispose(TmpRef);
+                                          hp1 :=  New(Pai386, op_reg_reg(A_ADD, S_L,
+                                            TRegister(Pai386(p)^.op2),TRegister(Pai386(p)^.op2)));
+                                        End;
+                                    hp1^.fileinfo := p^.fileinfo;
+                                    InsertLLItem(AsmL,p, p^.next, hp1);
+                                    New(TmpRef);
+                                    TmpRef^.segment := R_DEFAULT_SEG;
+                                    TmpRef^.symbol := nil;
+                                    TmpRef^.isintvalue := false;
+                                    TmpRef^.offset := 0;
+                                    TmpRef^.Index := TRegister(Pai386(p)^.op2);
+                                    TmpRef^.ScaleFactor := 2;
+                                    If (Pai386(p)^.op3t = Top_Reg)
+                                      Then
+                                        Begin
+                                          TmpRef^.base := R_NO;
+                                          hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
+                                            TRegister(twowords(Pai386(p)^.op2).word2)));
+                                        End
+                                      Else
+                                        Begin
+                                          TmpRef^.base := TRegister(Pai386(p)^.op2);
+                                          hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)));
+                                        End;
+                                    hp1^.fileinfo := p^.fileinfo;
+                                    InsertLLItem(AsmL,p^.previous, p^.next, hp1);
+                                    Dispose(p, Done);
+                                    p := Pai(hp1^.next);
+                                  End
+                                Else Dispose(TmpRef);
+                            End;
+                          9: Begin
+                             {imul 9, reg1, reg2 to
+                                lea (reg1,reg1,8), reg2
+                              imul 9, reg1 to
+                                lea (reg1,reg1,8), reg1}
+                               TmpRef^.base := TRegister(Pai386(p)^.op2);
+                               TmpRef^.Index := TRegister(Pai386(p)^.op2);
+                               TmpRef^.ScaleFactor := 8;
+                               If (Pai386(p)^.op3t = Top_None)
+                                   Then hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)))
+                                   Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
+                                     TRegister(twowords(Pai386(p)^.op2).word2)));
+                                 hp1^.fileinfo := p^.fileinfo;
+                                 InsertLLItem(AsmL,p^.previous, p^.next, hp1);
+                                 Dispose(p, Done);
+                                 p := hp1;
+                               End;
+                         10: Begin
+                            {imul 10, reg1, reg2 to
+                               lea (reg1,reg1,4), reg2
+                               add reg2, reg2
+                             imul 10, reg1 to
+                               lea (reg1,reg1,4), reg1
+                               add reg1, reg1}
+                               If (aktoptprocessor <= int486) Then
+                                 Begin
+                                   If (Pai386(p)^.op3t = Top_Reg)
+                                     Then
+                                       hp1 :=  New(Pai386, op_reg_reg(A_ADD, S_L,
+                                          Tregister(twowords(Pai386(p)^.op2).word2),
+                                          Tregister(twowords(Pai386(p)^.op2).word2)))
+                                     Else hp1 := New(Pai386, op_reg_reg(A_ADD, S_L,
+                                              TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)));
+                                   hp1^.fileinfo := p^.fileinfo;
+                                   InsertLLItem(AsmL,p, p^.next, hp1);
+                                   TmpRef^.base := TRegister(Pai386(p)^.op2);
+                                   TmpRef^.Index := TRegister(Pai386(p)^.op2);
+                                   TmpRef^.ScaleFactor := 4;
+                                   If (Pai386(p)^.op3t = Top_Reg)
+                                     Then
+                                       hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
+                                          TRegister(twowords(Pai386(p)^.op2).word2)))
+                                     Else
+                                       hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
+                                          TRegister(Pai386(p)^.op2)));
+                                   hp1^.fileinfo := p^.fileinfo;
+                                   InsertLLItem(AsmL,p^.previous, p^.next, hp1);
+                                   Dispose(p, Done);
+                                   p := Pai(hp1^.next);
+                                 End
+                               Else Dispose(TmpRef);
+                             End;
+                         12: Begin
+                            {imul 12, reg1, reg2 to
+                               lea (,reg1,4), reg2
+                               lea (,reg1,8) reg2
+                             imul 12, reg1 to
+                               lea (reg1,reg1,2), reg1
+                               lea (,reg1,4), reg1}
+                               If (aktoptprocessor <= int486)
+                                 Then
+                                   Begin
+                                     TmpRef^.Index := TRegister(Pai386(p)^.op2);
+                                     If (Pai386(p)^.op3t = Top_Reg)
+                                       Then
+                                         Begin
+                                           TmpRef^.base := TRegister(twowords(Pai386(p)^.op2).word2);
+                                           TmpRef^.ScaleFactor := 8;
+                                           hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
+                                             TRegister(twowords(Pai386(p)^.op2).word2)));
+                                         End
+                                       Else
+                                         Begin
+                                           TmpRef^.base := R_NO;
+                                           TmpRef^.ScaleFactor := 4;
+                                           hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
+                                             TRegister(Pai386(p)^.op2)));
+                                         End;
+                                     hp1^.fileinfo := p^.fileinfo;
+                                     InsertLLItem(AsmL,p, p^.next, hp1);
+                                     New(TmpRef);
+                                     TmpRef^.segment := R_DEFAULT_SEG;
+                                     TmpRef^.symbol := nil;
+                                     TmpRef^.isintvalue := false;
+                                     TmpRef^.offset := 0;
+                                     TmpRef^.Index := TRegister(Pai386(p)^.op2);
+                                     If (Pai386(p)^.op3t = Top_Reg)
+                                       Then
+                                         Begin
+                                           TmpRef^.base := R_NO;
+                                           TmpRef^.ScaleFactor := 4;
+                                           hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
+                                             TRegister(twowords(Pai386(p)^.op2).word2)));
+                                         End
+                                       Else
+                                         Begin
+                                           TmpRef^.base := TRegister(Pai386(p)^.op2);
+                                           TmpRef^.ScaleFactor := 2;
+                                           hp1 :=  New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
+                                             TRegister(Pai386(p)^.op2)));
+                                         End;
+                                     hp1^.fileinfo := p^.fileinfo;
+                                     InsertLLItem(AsmL,p^.previous, p^.next, hp1);
+                                     Dispose(p, Done);
+                                     p := Pai(hp1^.next);
+                                   End
+                                 Else Dispose(TmpRef);
+                             End
+                          Else Dispose(TmpRef);
+                        End;
+                      End;
+                End;
+              A_LEA:
+                Begin
+                {changes "lea (%reg1), %reg2" into "mov %reg1, %reg2"}
+                  If (PReference(Pai386(p)^.op1)^.Base >= R_EAX) And
+                     (PReference(Pai386(p)^.op1)^.Base <= R_EDI) And
+                     (PReference(Pai386(p)^.op1)^.Index = R_NO) And
+                     (PReference(Pai386(p)^.op1)^.Offset = 0) And
+                     (Not(Assigned(PReference(Pai386(p)^.op1)^.Symbol))) Then
+                    Begin
+                      hp1 := New(Pai386, op_reg_reg(A_MOV, S_L,PReference(Pai386(p)^.op1)^.Base,
+                        TRegister(Pai386(p)^.op2)));
+                      hp1^.fileinfo := p^.fileinfo;
+                      InsertLLItem(AsmL,p^.previous,p^.next, hp1);
+                      Dispose(p, Done);
+                      p := hp1;
+                      Continue;
+                    End;
+                End;
+              A_MOV:
+                Begin
+                  If (Pai386(p)^.op2t = top_reg) And
+                     (TRegister(Pai386(p)^.op2) In [{R_EAX, R_EBX, R_EDX, }R_EDI]) And
+                     GetNextInstruction(p, hp1) And
+                     (Pai(hp1)^.typ = ait_instruction) And
+                     (Pai386(hp1)^._operator = A_MOV) And
+                     (Pai386(hp1)^.op1t = top_reg) And
+                     (Pai386(hp1)^.op1 = Pai386(p)^.op2)
+                    Then
+                {we have "mov x, %treg; mov %treg, y}
+                      If (Pai386(hp1)^.op2t <> top_reg) Or
+                         (GetNextInstruction(hp1, hp2) And
+                         RegInInstruction(TRegister(Pai386(hp1)^.op2), hp2))
+                        Then
+               {we've got "mov x, %treg; mov %treg, y; XXX y" (ie. y is used in
+                the third instruction)}
+                          Case Pai386(p)^.op1t Of
+                            top_reg:
+                          {change "mov %reg, %treg; mov %treg, y"
+                           to "mov %reg, y"}
+                              Begin
+                                Pai386(hp1)^.op1 := Pai386(p)^.op1;
+                                AsmL^.Remove(p);
+                                Dispose(p, Done);
+                                p := hp1;
+                                continue;
+                              End;
+                            top_ref:
+                              If (Pai386(hp1)^.op2t = top_reg)
+                                Then
+                             {change "mov mem, %treg; mov %treg, %reg"
+                              to "mov mem, %reg"}
+                                  Begin
+                                    Pai386(p)^.op2 := Pai386(hp1)^.op2;
+                                    AsmL^.Remove(hp1);
+                                    Dispose(hp1, Done);
+                                    continue;
+                                  End;
+                          End
+                        Else
+               {remove an instruction which never makes sense: we've got
+                "mov mem, %reg1; mov %reg1, %edi" and then EDI isn't used anymore!}
+{                          Begin
+                            If (TRegister(Pai386(hp1)^.op2) = R_EDI) And
+                               Not(GetNextInstruction(hp1, hp2) And
+                                   (Pai(hp2)^.typ = ait_instruction) And
+                                   (Pai386(hp2)^.op2t = top_reg) And
+                                   (Pai386(hp2)^.op2 = Pointer(R_ESI))) Then
+                              Begin
+                                AsmL^.Remove(hp1);
+                                Dispose(hp1, Done);
+                                Continue;
+                              End
+                          End}
+                    Else
+                  {Change "mov %reg1, %reg2; xxx %reg2, ???" to
+                   "mov %reg1, %reg2; xxx %reg1, ???" to avoid a write/read
+                   penalty}
+                      If (Pai386(p)^.op1t = top_reg) And
+                         (Pai386(p)^.op2t = top_reg) And
+                         GetNextInstruction(p,hp1) And
+                         (Pai(hp1)^.typ = ait_instruction) And
+                         (Pai386(hp1)^.op1t = top_reg) And
+                         (Pai386(hp1)^.op1 = Pai386(p)^.op2)
+                        Then
+                  {we have "mov %reg1, %reg2; XXX %reg2, ???"}
+                          Begin
+                            If ((Pai386(hp1)^._operator = A_OR) Or
+                                (Pai386(hp1)^._operator = A_TEST)) And
+                               (Pai386(hp1)^.op2t = top_reg) And
+                               (Pai386(hp1)^.op1 = Pai386(hp1)^.op2)
+                              Then
+                   {we have "mov %reg1, %reg2; test/or %reg2, %reg2"}
+                                Begin
+                                  If GetNextInstruction(hp1, hp2) And
+                                     (Pai(hp2)^.typ = ait_labeled_instruction) And
+                                     (TRegister(Pai386(p)^.op2) <> R_ESI)
+                                    Then
+                   {change "mov %reg1, %reg2; test/or %reg2, %reg2; jxx" to
+                    "test %reg1, %reg1; jxx"}
+                                      Begin
+                                        Pai386(hp1)^.op1 := Pai386(p)^.op1;
+                                        Pai386(hp1)^.op2 := Pai386(p)^.op1;
+                                        AsmL^.Remove(p);
+                                        Dispose(p, done);
+                                        p := hp1;
+                                        continue
+                                      End
+                                    Else
+                   {change "mov %reg1, %reg2; test/or %reg2, %reg2" to
+                    "mov %reg1, %reg2; test/or %reg1, %reg1"}
+                                      Begin
+                                        Pai386(hp1)^.op1 := Pai386(p)^.op1;
+                                        Pai386(hp1)^.op2 := Pai386(p)^.op1;
+                                      End;
+                                End
+{                              Else
+                                If (Pai386(p^.next)^._operator
+                                   In [A_PUSH, A_OR, A_XOR, A_AND, A_TEST])}
+                         {change "mov %reg1, %reg2; push/or/xor/... %reg2, ???" to
+                          "mov %reg1, %reg2; push/or/xor/... %reg1, ???"}
+                          End
+                        Else
+                  {leave out the mov from "mov reg, x(%frame_pointer); leave/ret" (with
+                   x >= RetOffset) as it doesn't do anything (it writes either to a
+                   parameter or to the temporary storage room for the function
+                   result)}
+                          If GetNextInstruction(p, hp1) And
+                             (Pai(hp1)^.typ = ait_instruction)
+                            Then
+                              If ((Pai386(hp1)^._operator = A_LEAVE) Or
+                                  (Pai386(hp1)^._operator = A_RET)) And
+                                 (Pai386(p)^.op2t = top_ref) And
+                                 (TReference(Pai386(p)^.op2^).base = ProcInfo.FramePointer) And
+                                 (TReference(Pai386(p)^.op2^).offset >= ProcInfo.RetOffset) And
+                                 (TReference(Pai386(p)^.op2^).index = R_NO) And
+                                 (Pai386(p)^.op1t = top_reg)
+                                Then
+                                  Begin
+                                   AsmL^.Remove(p);
+                                   Dispose(p, done);
+                                   p := hp1;
+                                 End
+                               Else
+                                 If (Pai386(p)^.op1t = top_reg) And
+                                    (Pai386(p)^.op2t = top_ref) And
+                                    (Pai386(p)^.Size = Pai386(hp1)^.Size) And
+                                    (Pai386(hp1)^._operator = A_CMP) And
+                                    (Pai386(hp1)^.op2t = top_ref) And
+                                    RefsEqual(TReference(Pai386(p)^.op2^),
+                                              TReference(Pai386(hp1)^.op2^))
+                                   Then
+            {change "mov reg, mem1; cmp x, mem1" to "mov reg, mem1; cmp x, reg1"}
+                                     Begin
+                                       Dispose(PReference(Pai386(hp1)^.op2));
+                                       Pai386(hp1)^.opxt := Pai386(hp1)^.op1t + (top_reg shl 4);
+                                       Pai386(hp1)^.op2 := Pai386(p)^.op1
+                                     End;
+                { Next instruction is also a MOV ? }
+                  If GetNextInstruction(p, hp1) And
+                     (pai(hp1)^.typ = ait_instruction) and
+                     (Pai386(hp1)^._operator = A_MOV)
+                    Then
+                      Begin
+                        If (Pai386(hp1)^.op1t = Pai386(p)^.op2t) and
+                           (Pai386(hp1)^.op2t = Pai386(p)^.op1t)
+                          Then
+                            {mov reg1, mem1     or     mov mem1, reg1
+                             mov mem2, reg2            mov reg2, mem2}
+                            Begin
+                              If (Pai386(hp1)^.op2t = top_ref)
+                                Then
+                                  TmpBool1 := RefsEqual(TReference(Pai386(hp1)^.op2^), TReference(Pai386(p)^.op1^))
+                                Else
+                                  TmpBool1 := Pai386(hp1)^.op2 = Pai386(p)^.op1;
+                              If TmpBool1
+                                Then
+                            {mov reg1, mem1     or     mov mem1, reg1
+                             mov mem2, reg1            mov reg2, mem1}
+                                  Begin
+                                    If (Pai386(hp1)^.op1t = top_ref)
+                                      Then
+                                        TmpBool1 := RefsEqual(TReference(Pai386(hp1)^.op1^),
+                                                              TReference(Pai386(p)^.op2^))
+                                      Else TmpBool1 := (Pai386(hp1)^.op1 = Pai386(p)^.op2);
+                                   If TmpBool1 Then
+                        { Removes the second statement from
+                            mov reg1, mem1
+                            mov mem1, reg1 }
+                                      Begin
+                                        AsmL^.remove(hp1);
+                                        Dispose(hp1,done);
+                                      End;
+                                  End
+                                Else
+                                  Begin
+                                    If GetNextInstruction(hp1, hp2) And
+                                       (Pai386(p)^.op1t = top_ref) And
+                                       (Pai386(p)^.op2t = top_reg) And
+                                       (Pai386(hp1)^.op1t = top_reg) And
+                                       (Pai386(hp1)^.op1 = Pai386(p)^.op2) And
+                                       (Pai386(hp1)^.op2t = top_ref) And
+                                       (Pai(hp2)^.typ = ait_instruction) And
+                                       (Pai386(hp2)^._operator = A_MOV) And
+                                       (Pai386(hp2)^.op2t = top_reg) And
+                                       (Pai386(hp2)^.op1t = top_ref) And
+                                       RefsEqual(TReference(Pai386(hp2)^.op1^),
+                                                 TReference(Pai386(hp1)^.op2^))
+                                      Then
+                                        If (TRegister(Pai386(p)^.op2) = R_EDI)
+                                          Then
+                                 {   mov mem1, reg1
+                                     mov reg1, mem2
+                                     mov mem2, reg2
+                                  to:
+                                     mov mem1, reg2
+                                     mov reg2, mem2}
+                                            Begin
+                                              Pai386(p)^.op2 := Pai386(hp2)^.op2;
+                                              Pai386(hp1)^.op1 := Pai386(hp2)^.op2;
+                                              AsmL^.Remove(hp2);
+                                              Dispose(hp2,Done);
+                                            End
+                                          Else
+                                 {   mov mem1, reg1
+                                     mov reg1, mem2
+                                     mov mem2, reg2
+                                  to:
+                                     mov mem1, reg1
+                                     mov mem1, reg2
+                                     mov reg1, mem2}
+                                            Begin
+                                              Pai386(hp1)^.opxt := top_ref + top_reg shl 4;
+                                              Pai386(hp1)^.op1 := Pai386(hp1)^.op2; {move the treference}
+                                              TReference(Pai386(hp1)^.op1^) := TReference(Pai386(p)^.op1^);
+                                              If Assigned(TReference(Pai386(p)^.op1^).Symbol) Then
+                                                Begin
+                                                  New(TReference(Pai386(hp1)^.op1^).Symbol);
+                                                  TReference(Pai386(hp1)^.op1^).Symbol^ :=
+                                                      TReference(Pai386(p)^.op1^).Symbol^;
+                                                End;
+                                              Pai386(hp1)^.op2 := Pai386(hp2)^.op2;
+                                              Pai386(hp2)^.opxt := top_reg + top_ref shl 4;
+                                              Pai386(hp2)^.op2 := Pai386(hp2)^.op1;
+                                              Pai386(hp2)^.op1 := Pai386(p)^.op2;
+                                            End;
+                                  End;
+                            End
+                          Else
+(*                          {movl [mem1],reg1
+                             movl [mem1],reg2
+                            to:
+                              movl [mem1],reg1
+                              movl reg1,reg2 }
+                            If (Pai386(p)^.op1t = top_ref) and
+                               (Pai386(p)^.op2t = top_reg) and
+                               (Pai386(hp1)^.op1t = top_ref) and
+                               (Pai386(hp1)^.op2t = top_reg) and
+                               (Pai386(p)^.size = Pai386(hp1)^.size) and
+                               RefsEqual(TReference(Pai386(p)^.op1^),TReference(Pai386(hp1)^.op1^)) and
+                               (TRegister(Pai386(p)^.op2)<>TReference(Pai386(hp1)^.op1^).base) and
+                               (TRegister(Pai386(p)^.op2)<>TReference(Pai386(hp1)^.op1^).index) then
+                              Begin
+                                Dispose(PReference(Pai386(hp1)^.op1));
+                                Pai386(hp1)^.op1:=Pai386(p)^.op2;
+                                Pai386(hp1)^.opxt:=Top_reg+Top_reg shl 4;
+                              End
+                            Else*)
+                            {   movl const1,[mem1]
+                                movl [mem1],reg1
+                             to:
+                                movl const1,reg1
+                                movl reg1,[mem1] }
+                              If (Pai386(p)^.op1t = top_const) and
+                                 (Pai386(p)^.op2t = top_ref) and
+                                 (Pai386(hp1)^.op1t = top_ref) and
+                                 (Pai386(hp1)^.op2t = top_reg) and
+                                 (Pai386(p)^.size = Pai386(hp1)^.size) and
+                                 RefsEqual(TReference(Pai386(hp1)^.op1^),TReference(Pai386(p)^.op2^)) then
+                                Begin
+                                  Pai386(hp1)^.op1:=Pai386(hp1)^.op2;
+                                  Pai386(hp1)^.op2:=Pai386(p)^.op2;
+                                  Pai386(hp1)^.opxt:=Top_reg+Top_ref shl 4;
+                                  Pai386(p)^.op2:=Pai386(hp1)^.op1;
+                                  Pai386(p)^.opxt:=Top_const+(top_reg shl 4);
+                                End
+                      End;
+                       {changes "mov $0, %reg" into "xor %reg, %reg"}
+                  If (Pai386(p)^.op1t = Top_Const) And
+                     (Pai386(p)^.op1 = Pointer(0)) And
+                     (Pai386(p)^.op2t = Top_Reg)
+                    Then
+                      Begin
+                        Pai386(p)^._operator := A_XOR;
+                        Pai386(p)^.opxt := Top_Reg+Top_reg shl 4;
+                        Pai386(p)^.op1 := Pai386(p)^.op2;
+                      End;
+                End;
+              A_MOVZX:
+                Begin
+                {removes superfluous And's after movzx's}
+                  If (Pai386(p)^.op2t = top_reg) And
+                     GetNextInstruction(p, hp1) And
+                     (Pai(hp1)^.typ = ait_instruction) And
+                     (Pai386(hp1)^._operator = A_AND) And
+                     (Pai386(hp1)^.op1t = top_const) And
+                     (Pai386(hp1)^.op2t = top_reg) And
+                     (Pai386(hp1)^.op2 = Pai386(p)^.op2)
+                    Then
+                      Case Pai386(p)^.Size Of
+                        S_BL, S_BW:
+                          If (Longint(Pai386(hp1)^.op1) = $ff)
+                            Then
+                              Begin
+                                AsmL^.Remove(hp1);
+                                Dispose(hp1, Done);
+                              End;
+                        S_WL:
+                          If (Longint(Pai386(hp1)^.op1) = $ffff)
+                            Then
+                              Begin
+                                AsmL^.Remove(hp1);
+                                Dispose(hp1, Done);
+                              End;
+                      End;
+                {changes some movzx constructs to faster synonims (all examples
+                 are given with eax/ax, but are also valid for other registers)}
+                  If (Pai386(p)^.op2t = top_reg) Then
+                    If (Pai386(p)^.op1t = top_reg)
+                      Then
+                        Case Pai386(p)^.size of
+                          S_BW:
+                            Begin
+                              If (TRegister(Pai386(p)^.op1) = Reg16ToReg8(TRegister(Pai386(p)^.op2))) And
+                                 Not(CS_LittleSize In AktSwitches)
+                                Then
+                                  {Change "movzbw %al, %ax" to "andw $0x0ffh, %ax"}
+                                  Begin
+                                    Pai386(p)^._operator := A_AND;
+                                    Pai386(p)^.opxt := top_const+Top_reg shl 4;
+                                    Longint(Pai386(p)^.op1) := $ff;
+                                    Pai386(p)^.Size := S_W
+                                  End
+                                Else
+                                  If GetNextInstruction(p, hp1) And
+                                     (Pai(hp1)^.typ = ait_instruction) And
+                                     (Pai386(hp1)^._operator = A_AND) And
+                                     (Pai386(hp1)^.op1t = top_const) And
+                                     (Pai386(hp1)^.op2t = top_reg) And
+                                     (Pai386(hp1)^.op2 = Pai386(p)^.op2)
+                                    Then
+                                      {Change "movzbw %reg1, %reg2; andw $const, %reg2"
+                                       to "movw %reg1, reg2; andw $(const1 and $ff), %reg2"}
+                                      Begin
+                                        Pai386(p)^._operator := A_MOV;
+                                        Pai386(p)^.Size := S_W;
+                                        Pai386(p)^.op1 := Pointer(Reg8ToReg16(TRegister(Pai386(p)^.op1)));
+                                        Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ff);
+                                      End;
+                            End;
+                          S_BL:
+                            Begin
+                              If (TRegister(Pai386(p)^.op1) = Reg32ToReg8(TRegister(Pai386(p)^.op2))) And
+                                 Not(CS_LittleSize in AktSwitches)
+                                Then
+                                  {Change "movzbl %al, %eax" to "andl $0x0ffh, %eax"}
+                                  Begin
+                                    Pai386(p)^._operator := A_AND;
+                                    Pai386(p)^.opxt := top_const+Top_reg shl 4;
+                                    Longint(Pai386(p)^.op1) := $ff;
+                                    Pai386(p)^.Size := S_L;
+                                  End
+                                Else
+                                  If GetNextInstruction(p, hp1) And
+                                     (Pai(hp1)^.typ = ait_instruction) And
+                                     (Pai386(hp1)^._operator = A_AND) And
+                                     (Pai386(hp1)^.op1t = top_const) And
+                                     (Pai386(hp1)^.op2t = top_reg) And
+                                     (Pai386(hp1)^.op2 = Pai386(p)^.op2)
+                                    Then
+                                     {Change "movzbl %reg1, %reg2; andl $const, %reg2"
+                                      to "movl %reg1, reg2; andl $(const1 and $ff), %reg2"}
+                                      Begin
+                                        Pai386(p)^._operator := A_MOV;
+                                        Pai386(p)^.Size := S_L;
+                                        Pai386(p)^.op1 := Pointer(Reg8ToReg32(TRegister(Pai386(p)^.op1)));
+                                        Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ff);
+                                      End
+                            End;
+                          S_WL:
+                            Begin
+                              If (TRegister(Pai386(p)^.op1) = Reg32ToReg16(TRegister(Pai386(p)^.op2))) And
+                                 Not(CS_LittleSize In AktSwitches)
+                                Then
+                                 {Change "movzwl %ax, %eax" to "andl $0x0ffffh, %eax"}
+                                  Begin
+                                    Pai386(p)^._operator := A_AND;
+                                    Pai386(p)^.opxt := top_const+Top_reg shl 4;
+                                    Longint(Pai386(p)^.op1) := $ffff;
+                                    Pai386(p)^.Size := S_L
+                                  End
+                                Else
+                                  If GetNextInstruction(p, hp1) And
+                                     (Pai(hp1)^.typ = ait_instruction) And
+                                     (Pai386(hp1)^._operator = A_AND) And
+                                     (Pai386(hp1)^.op1t = top_const) And
+                                     (Pai386(hp1)^.op2t = top_reg) And
+                                     (Pai386(hp1)^.op2 = Pai386(p)^.op2)
+                                    Then
+                                      {Change "movzwl %reg1, %reg2; andl $const, %reg2"
+                                       to "movl %reg1, reg2; andl $(const1 and $ffff), %reg2"}
+                                      Begin
+                                        Pai386(p)^._operator := A_MOV;
+                                        Pai386(p)^.Size := S_L;
+                                        Pai386(p)^.op1 := Pointer(Reg16ToReg32(TRegister(Pai386(p)^.op1)));
+                                        Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ffff);
+                                      End;
+                            End;
+                        End
+                      Else
+                        If (Pai386(p)^.op1t = top_ref) Then
+                          Begin
+                            If GetNextInstruction(p, hp1) And
+                               (Pai(hp1)^.typ = ait_instruction) And
+                               (Pai386(hp1)^._operator = A_AND) And
+                               (Pai386(hp1)^.op1t = Top_Const) And
+                               (Pai386(hp1)^.op2t = Top_Reg) And
+                               (Pai386(hp1)^.op2 = Pai386(p)^.op2) Then
+                              Begin
+                                Pai386(p)^._operator := A_MOV;
+                                Case Pai386(p)^.Size Of
+                                  S_BL:
+                                    Begin
+                                      Pai386(p)^.Size := S_L;
+                                      Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
+                                        And $ff);
+                                    End;
+                                  S_WL:
+                                    Begin
+                                      Pai386(p)^.Size := S_L;
+                                      Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
+                                        And $ffff);
+                                    End;
+                                  S_BW:
+                                    Begin
+                                      Pai386(p)^.Size := S_W;
+                                      Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
+                                        And $ff);
+                                    End;
+                                End;
+                              End;
+                          End;
+                End;
+              A_POP:
+                Begin
+                   if (Pai386(p)^.op1t = top_reg) And
+                      GetNextInstruction(p, hp1) And
+                      (pai(hp1)^.typ=ait_instruction) and
+                      (Pai386(hp1)^._operator=A_PUSH) and
+                      (Pai386(hp1)^.op1t = top_reg) And
+                      (Pai386(hp1)^.op1=Pai386(p)^.op1) then
+                     If (Not(cs_maxoptimieren in aktswitches)) Then
+                       Begin
+                         hp2:=pai(hp1^.next);
+                         asml^.remove(p);
+                         asml^.remove(hp1);
+                         dispose(p,done);
+                         dispose(hp1,done);
+                         p:=hp2;
+                         continue
+                       End
+                     Else
+                       Begin
+                         Pai386(p)^._operator := A_MOV;
+                         Pai386(p)^.op2 := Pai386(p)^.op1;
+                         Pai386(p)^.opxt := top_ref + top_reg shl 4;
+                         New(TmpRef);
+                         TmpRef^.segment := R_DEFAULT_SEG;
+                         TmpRef^.base := R_ESP;
+                         TmpRef^.index := R_NO;
+                         TmpRef^.scalefactor := 1;
+                         TmpRef^.symbol := nil;
+                         TmpRef^.isintvalue := false;
+                         TmpRef^.offset := 0;
+                         Pai386(p)^.op1 := Pointer(TmpRef);
+                         hp1 := Pai(p^.next);
+                         AsmL^.Remove(hp1);
+                         Dispose(hp1, Done)
+                       End
+                end;
+              A_PUSH:
+                Begin
+                  If (Pai386(p)^.size = S_W) And
+                     (Pai386(p)^.op1t = Top_Const) And
+                     GetNextInstruction(p, hp1) And
+                     (Pai(hp1)^.typ = ait_instruction) And
+                     (Pai386(hp1)^._operator = A_PUSH) And
+                     (Pai386(hp1)^.op1t = Top_Const) And
+                     (Pai386(hp1)^.size = S_W) Then
+                    Begin
+                      Pai386(p)^.Size := S_L;
+                      Pai386(p)^.op1 := Pointer(Longint(Pai386(p)^.op1) shl 16 + Longint(Pai386(hp1)^.op1));
+                      AsmL^.Remove(hp1);
+                      Dispose(hp1, Done)
+                    End;
+                End;
+              A_SHL, A_SAL:
+                Begin
+                  If (Pai386(p)^.op1t = Top_Const) And
+                     (Pai386(p)^.op2t = Top_Reg) And
+                     (Pai386(p)^.Size = S_L) And
+                     (Longint(Pai386(p)^.op1) <= 3)
+                {Changes "shl const, %reg32; add const/reg, %reg32" to one lea statement}
+                    Then
+                      Begin
+                        TmpBool1 := True; {should we check the next instruction?}
+                        TmpBool2 := False; {have we found an add/sub which could be
+                                            integrated in the lea?}
+                        New(TmpRef);
+                        TmpRef^.segment := R_DEFAULT_SEG;
+                        TmpRef^.base := R_NO;
+                        TmpRef^.index := TRegister(Pai386(p)^.op2);
+                        TmpRef^.scalefactor := PowerOf2(Longint(Pai386(p)^.op1));
+                        TmpRef^.symbol := nil;
+                        TmpRef^.isintvalue := false;
+                        TmpRef^.offset := 0;
+                        While TmpBool1 And
+                              GetNextInstruction(p, hp1) And
+                              (Pai(hp1)^.typ = ait_instruction) And
+                              ((Pai386(hp1)^._operator = A_ADD) Or
+                               (Pai386(hp1)^._operator = A_SUB)) And
+                              (Pai386(hp1)^.op2t = Top_Reg) And
+                              (Pai386(hp1)^.op2 = Pai386(p)^.op2) Do
+                          Begin
+                            TmpBool1 := False;
+                            If (Pai386(hp1)^.op1t = Top_Const)
+                              Then
+                                Begin
+                                  TmpBool1 := True;
+                                  TmpBool2 := True;
+                                  If Pai386(hp1)^._operator = A_ADD
+                                    Then Inc(TmpRef^.offset, Longint(Pai386(hp1)^.op1))
+                                    Else Dec(TmpRef^.offset, Longint(Pai386(hp1)^.op1));
+                                  AsmL^.Remove(hp1);
+                                  Dispose(hp1, Done);
+                                End
+                              Else
+                                If (Pai386(hp1)^.op1t = Top_Reg) And
+                                   (Pai386(hp1)^._operator = A_ADD) And
+                                   (TmpRef^.base = R_NO) Then
+                                  Begin
+                                    TmpBool1 := True;
+                                    TmpBool2 := True;
+                                    TmpRef^.base := TRegister(Pai386(hp1)^.op1);
+                                    AsmL^.Remove(hp1);
+                                    Dispose(hp1, Done);
+                                  End;
+                          End;
+                        If TmpBool2 Or
+                           ((aktoptprocessor < PentiumPro) And
+                            (Longint(Pai386(p)^.op1) <= 3) And
+                            Not(CS_LittleSize in AktSwitches))
+                          Then
+                            Begin
+                              If Not(TmpBool2) And
+                                 (Longint(Pai386(p)^.op1) = 1)
+                                Then
+                                  Begin
+                                    Dispose(TmpRef);
+                                    hp1 := new(Pai386,op_reg_reg(A_ADD,Pai386(p)^.Size,
+                                               TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)))
+                                  End
+                                Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
+                                                TRegister(Pai386(p)^.op2)));
+                              hp1^.fileinfo := p^.fileinfo;
+                              InsertLLItem(AsmL,p^.previous, p^.next, hp1);
+                              Dispose(p, Done);
+                              p := hp1;
+                            End;
+                      End
+                    Else
+                      If (aktoptprocessor < PentiumPro) And
+                         (Pai386(p)^.op1t = top_const) And
+                         (Pai386(p)^.op2t = top_reg) Then
+                        If (Longint(Pai386(p)^.op1) = 1)
+                          Then
+  {changes "shl $1, %reg" to "add %reg, %reg", which is the same on a 386,
+   but faster on a 486, and pairable in both U and V pipes on the Pentium
+   (unlike shl, which is only pairable in the U pipe)}
+                            Begin
+                              hp1 := new(Pai386,op_reg_reg(A_ADD,Pai386(p)^.Size,
+                                         TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)));
+                              hp1^.fileinfo := p^.fileinfo;
+                              InsertLLItem(AsmL,p^.previous, p^.next, hp1);
+                              Dispose(p, done);
+                              p := hp1;
+                            End
+                          Else If (Pai386(p)^.size = S_L) and
+                                  (Longint(Pai386(p)^.op1) <= 3) Then
+                    {changes "shl $2, %reg" to "lea (,%reg,4), %reg"
+                             "shl $3, %reg" to "lea (,%reg,8), %reg}
+                                 Begin
+                                   New(TmpRef);
+                                   TmpRef^.segment := R_DEFAULT_SEG;
+                                   TmpRef^.base := R_NO;
+                                   TmpRef^.index := TRegister(Pai386(p)^.op2);
+                                   TmpRef^.scalefactor := PowerOf2(Longint(Pai386(p)^.op1));
+                                   TmpRef^.symbol := nil;
+                                   TmpRef^.isintvalue := false;
+                                   TmpRef^.offset := 0;
+                                   hp1 := new(Pai386,op_ref_reg(A_LEA,S_L,TmpRef, TRegister(Pai386(p)^.op2)));
+                                   hp1^.fileinfo := p^.fileinfo;
+                                   InsertLLItem(AsmL,p^.previous, p^.next, hp1);
+                                   Dispose(p, done);
+                                   p := hp1;
+                                 End
+                End;
+              A_SAR, A_SHR:
+                  {changes the code sequence
+                   shr/sar const1, %reg
+                   shl     const2, %reg
+                   to either "sar/and", "shl/and" or just "and" depending on const1 and const2}
+                Begin
+                  If GetNextInstruction(p, hp1) And
+                     (pai(hp1)^.typ = ait_instruction) and
+                     (Pai386(hp1)^._operator = A_SHL) and
+                     (Pai386(p)^.op1t = top_const) and
+                     (Pai386(hp1)^.op1t = top_const)
+                    Then
+                      If (Longint(Pai386(p)^.op1) > Longint(Pai386(hp1)^.op1)) And
+                         (Pai386(p)^.op2t = Top_reg) And
+                         Not(CS_LittleSize In AktSwitches) And
+                         ((Pai386(p)^.Size = S_B) Or
+                          (Pai386(p)^.Size = S_L))
+                        Then
+                          Begin
+                            Dec(Longint(Pai386(p)^.op1), Longint(Pai386(hp1)^.op1));
+                            Pai386(hp1)^._operator := A_And;
+                            Pai386(hp1)^.op1 := Pointer(PowerOf2(Longint(Pai386(hp1)^.op1))-1);
+                            If (Pai386(p)^.Size = S_L)
+                              Then Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffffffff)
+                              Else Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
+                          End
+                        Else
+                          If (Longint(Pai386(p)^.op1) < Longint(Pai386(hp1)^.op1)) And
+                             (Pai386(p)^.op2t = Top_reg) And
+                             Not(CS_LittleSize In AktSwitches) And
+                             ((Pai386(p)^.Size = S_B) Or
+                              (Pai386(p)^.Size = S_L))
+                            Then
+                              Begin
+                                Dec(Longint(Pai386(hp1)^.op1), Longint(Pai386(p)^.op1));
+                                Pai386(p)^._operator := A_And;
+                                Pai386(p)^.op1 := Pointer(PowerOf2(Longint(Pai386(p)^.op1))-1);
+                                If (Pai386(p)^.Size = S_L)
+                                  Then Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffffffff)
+                                  Else Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
+                              End
+                            Else
+                              Begin
+                                Pai386(p)^._operator := A_And;
+                                Pai386(p)^.op1 := Pointer(PowerOf2(Longint(Pai386(p)^.op1))-1);
+                                Case Pai386(p)^.Size Of
+                                  S_B: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
+                                  S_W: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffff);
+                                  S_L: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor
+                                         $ffffffff);
+                                End;
+                                AsmL^.remove(hp1);
+                                dispose(hp1, done);
+                              End;
+                End;
+              A_SUB:
+                {change "subl $2, %esp; pushw x" to "pushl x"}
+                Begin
+                  If (Pai386(p)^.op1t = top_const) And
+                     (Longint(Pai386(p)^.op1) = 2) And
+                     (Pai386(p)^.op2t = top_reg) And
+                     (TRegister(Pai386(p)^.op2) = R_ESP)
+                    Then
+                      Begin
+                        hp1 := Pai(p^.next);
+                        While Assigned(hp1) And
+                              (Pai(hp1)^.typ In [ait_instruction]+SkipInstr) And
+                               Not((Pai(hp1)^.typ = ait_instruction) And
+                                   ((Pai386(hp1)^._operator = A_PUSH) or
+                                    ((Pai386(hp1)^._operator = A_MOV) And
+                                     (Pai386(hp1)^.op2t = top_ref) And
+                                     (TReference(Pai386(hp1)^.op2^).base = R_ESP)))) do
+                          hp1 := Pai(hp1^.next);
+                        If Assigned(hp1) And
+                            (Pai(hp1)^.typ = ait_instruction) And
+                            (Pai386(hp1)^._operator = A_PUSH) And
+                            (Pai386(hp1)^.Size = S_W)
+                          Then
+                            Begin
+                              Pai386(hp1)^.size := S_L;
+                              If (Pai386(hp1)^.op1t = top_reg) Then
+                                Pai386(hp1)^.op1 := Pointer(Reg16ToReg32(TRegister(Pai386(hp1)^.op1)));
+                              hp1 := Pai(p^.next);
+                              AsmL^.Remove(p);
+                              Dispose(p, Done);
+                              p := hp1;
+                              Continue
+                            End
+                          Else
+                            If GetLastInstruction(p, hp1) And
+                               (Pai(hp1)^.typ = ait_instruction) And
+                               (Pai386(hp1)^._operator = A_SUB) And
+                               (Pai386(hp1)^.op1t = top_const) And
+                               (Pai386(hp1)^.op2t = top_reg) And
+                               (TRegister(Pai386(hp1)^.Op2) = R_ESP)
+                              Then
+                                Begin
+                                  Inc(Longint(Pai386(p)^.op1), Longint(Pai386(hp1)^.op1));
+                                  AsmL^.Remove(hp1);
+                                  Dispose(hp1, Done);
+                                End;
+                      End;
+                End;
+              A_TEST, A_OR:
+                {removes the line marked with (x) from the sequence
+                 And/or/xor/add/sub/... $x, %y
+                 test/or %y, %y   (x)
+                 j(n)z _Label
+                    as the first instruction already adjusts the ZF}
+                 Begin
+                   If (Pai386(p)^.op1 = Pai386(p)^.op2) And
+                      GetLastInstruction(p, hp1) And
+                      (pai(hp1)^.typ = ait_instruction) Then
+                     Case Pai386(hp1)^._operator Of
+                       A_ADD, A_SUB, A_OR, A_XOR, A_AND, A_SHL, A_SHR:
+                         Begin
+                           If (Pai386(hp1)^.op2 = Pai386(p)^.op1) Then
+                             Begin
+                               hp1 := pai(p^.next);
+                               asml^.remove(p);
+                               dispose(p, done);
+                               p := pai(hp1);
+                               continue
+                             End;
+                         End;
+                       A_DEC, A_INC, A_NEG:
+                         Begin
+                           If (Pai386(hp1)^.op1 = Pai386(p)^.op1) Then
+                             Begin
+                               hp1 := pai(p^.next);
+                               asml^.remove(p);
+                               dispose(p, done);
+                               p := pai(hp1);
+                               continue
+                             End;
+                         End
+                     End;
+                 End;
+            End;
+          End;
+        ait_label:
+          Begin
+            If Not(Pai_Label(p)^.l^.is_used)
+              Then
+                Begin
+                  hp1 := Pai(p^.next);
+                  AsmL^.Remove(p);
+                  Dispose(p, Done);
+                  p := hp1;
+                  Continue
+                End;
+          End;
+{$ifdef regalloc}
+        ait_regalloc: UsedRegs := UsedRegs + [PaiAlloc(p)^.Reg];
+        ait_regdealloc: UsedRegs := UsedRegs - [PaiAlloc(p)^.Reg];
+{$endif regalloc}
+      End;
+      p:=pai(p^.next);
+    end;
+end;
+
+Procedure PeepHoleOptPass2(AsmL: PAasmOutput);
+
+var
+  p,hp1,hp2 : pai;
+  TmpBool1, TmpBool2: Boolean;
+
+  TmpRef: PReference;
+
+{$IfDef RegAlloc}
+  RegsUsed: Set of TRegister;
+{$EndIf RegAlloc}
+Begin
+  P := Pai(AsmL^.First);
+  While Assigned(p) Do
+    Begin
+      Case P^.Typ Of
+        Ait_Instruction:
+          Begin
+            Case Pai386(p)^._operator Of
+              A_MOVZX:
+                Begin
+                  If (Pai386(p)^.op2t = top_reg) Then
+                    If (Pai386(p)^.op1t = top_reg)
+                      Then
+                        Case Pai386(p)^.size of
+                          S_BL:
+                            Begin
+                              If IsGP32Reg(TRegister(Pai386(p)^.op2)) And
+                                 Not(CS_LittleSize in AktSwitches) And
+                                 (aktoptprocessor >= Pentium) And
+                                 (aktoptprocessor < PentiumPro)
+                                Then
+                                  {Change "movzbl %reg1, %reg2" to
+                                   "xorl %reg2, %reg2; movb %reg1, %reg2" for Pentium and
+                                   PentiumMMX}
+                                  Begin
+                                    hp1 := New(Pai386, op_reg_reg(A_XOR, S_L,
+                                               TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)));
+                                    hp1^.fileinfo := p^.fileinfo;
+                                    InsertLLItem(AsmL,p^.previous, p, hp1);
+                                    Pai386(p)^._operator := A_MOV;
+                                    Pai386(p)^.size := S_B;
+                                    Pai386(p)^.op2 :=
+                                      Pointer(Reg32ToReg8(TRegister(Pai386(p)^.op2)));
+                                    InsertLLItem(AsmL,p, p^.next, hp2);
+                                  End;
+                            End;
+                        End
+                      Else
+                        If (Pai386(p)^.op1t = top_ref) And
+                           (PReference(Pai386(p)^.op1)^.base <> TRegister(Pai386(p)^.op2)) And
+                           (PReference(Pai386(p)^.op1)^.index <> TRegister(Pai386(p)^.op2)) And
+                           Not(CS_LittleSize in AktSwitches) And
+                           IsGP32Reg(TRegister(Pai386(p)^.op2)) And
+                           (aktoptprocessor >= Pentium) And
+                           (aktoptprocessor < PentiumPro) And
+                           (Pai386(p)^.Size = S_BL)
+                          Then
+                            {changes "movzbl mem, %reg" to "xorl %reg, %reg; movb mem, %reg8" for
+                             Pentium and PentiumMMX}
+                            Begin
+                              hp1 := New(Pai386,op_reg_reg(A_XOR, S_L, TRegister(Pai386(p)^.op2),
+                                         TRegister(Pai386(p)^.op2)));
+                              hp1^.fileinfo := p^.fileinfo;
+                              Pai386(p)^._operator := A_MOV;
+                              Pai386(p)^.size := S_B;
+                              Pai386(p)^.op2 := Pointer(Reg32ToReg8(TRegister(Pai386(p)^.op2)));
+                              InsertLLItem(AsmL,p^.previous, p, hp1);
+                            End;
+                End;
+            End;
+          End;
+      End;
+      p := Pai(p^.next)
+    End;
+End;
+
+End.
+
+{
+ $log$
+}