fpc/compiler/new/i386/aoptcpud.pas
2002-09-07 15:25:00 +00:00

242 lines
8.3 KiB
ObjectPascal

{
$Id$
Copyright (c) 1998-2000 by Jonas Maebe, member of the Free Pascal
Development Team
This unit contains the processor specific implementation of the
assembler optimizer data flow analyzer.
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 aoptcpud;
Interface
uses Aasm, cpubase, AoptCpub, AoptObj, AoptDA;
Type
PAOptDFACpu = ^TAOptDFACpu;
TAOptDFACpu = Object(TAOptDFA)
{ uses the same constructor as TAoptDFA = constructor from TAoptObj }
{ handles the processor dependent dataflow analizing }
Procedure CpuDFA(p: PInstr); Virtual;
Function TCh2Reg(Ch: TInsChange): TRegister; Virtual;
Function RegReadByInstr(Reg: TRegister; p: Pai): Boolean; Virtual;
End;
Implementation
uses cpuinfo;
Procedure TAOptDFACpu.CpuDFA(p: PInstr);
{ Analyzes the Data Flow of an assembler list. Analyses the reg contents }
{ for the instructions between blockstart and blockend. Returns the last pai }
{ which has been processed }
Var CurProp: PPaiProp;
InstrProp: TInsProp;
TmpRef: TReference;
Cnt: Byte;
Begin
CurProp := PPaiProp(p^.OptInfo);
Case p^.Opcode Of
A_DIV, A_IDIV, A_MUL:
Begin
CurProp^.ReadOp(p^.oper[0]);
CurProp^.ReadReg(R_EAX);
If (p^.OpCode = A_IDIV) or
(p^.OpCode = A_DIV) Then
CurProp^.ReadReg(R_EDX);
CurProp^.DestroyReg(R_EAX, InstrSinceLastMod)
End;
A_IMUL:
Begin
CurProp^.ReadOp(p^.oper[0]);
CurProp^.ReadOp(p^.oper[1]);
If (p^.oper[2].typ = top_none) Then
If (p^.oper[1].typ = top_none) Then
Begin
CurProp^.ReadReg(R_EAX);
CurProp^.DestroyReg(R_EAX, InstrSinceLastMod);
CurProp^.DestroyReg(R_EDX, InstrSinceLastMod)
End
Else
CurProp^.ModifyOp(p^.oper[1], InstrSinceLastMod)
Else
CurProp^.ModifyOp(p^.oper[2], InstrSinceLastMod);
End;
A_XOR:
Begin
CurProp^.ReadOp(p^.oper[0]);
CurProp^.ReadOp(p^.oper[1]);
If (p^.oper[0].typ = top_reg) And
(p^.oper[1].typ = top_reg) And
(p^.oper[0].reg = p^.oper[1].reg) Then
Begin
CurProp^.DestroyReg(p^.oper[0].reg, InstrSinceLastMod);
CurProp^.Regs[RegMaxSize(p^.oper[0].reg)].typ := Con_Const;
CurProp^.Regs[RegMaxSize(p^.oper[0].reg)].StartMod := Pointer(0)
End
Else
CurProp^.ModifyOp(p^.oper[1], InstrSinceLastMod);
End
Else
Begin
InstrProp := InsProp[p^.OpCode];
Cnt := 1;
While (Cnt <= MaxCh) And
(InstrProp.Ch[Cnt] <> Ch_None) Do
Begin
Case InstrProp.Ch[Cnt] Of
Ch_REAX..Ch_REDI:
CurProp^.ReadReg(TCh2Reg(InstrProp.Ch[Cnt]));
Ch_WEAX..Ch_RWEDI:
Begin
If (InstrProp.Ch[Cnt] >= Ch_RWEAX) Then
CurProp^.ReadReg(TCh2Reg(InstrProp.Ch[Cnt]));
CurProp^.DestroyReg(TCh2Reg(InstrProp.Ch[Cnt]),InstrSinceLastMod);
End;
Ch_MEAX..Ch_MEDI:
CurProp^.ModifyReg(TCh2Reg(InstrProp.Ch[Cnt]), InstrSinceLastMod);
Ch_CDirFlag: CurProp^.CondRegs.ClearFlag(DirFlag);
Ch_SDirFlag: CurProp^.CondRegs.SetFlag(DirFlag);
Ch_Rop1: CurProp^.ReadOp(p^.oper[0]);
Ch_Rop2: CurProp^.ReadOp(p^.oper[1]);
Ch_Rop3: CurProp^.ReadOp(p^.oper[2]);
Ch_Wop1..Ch_RWop1:
Begin
If (InstrProp.Ch[Cnt] = Ch_RWop1) Then
CurProp^.ReadOp(p^.oper[0]);
CurProp^.DestroyOp(p^.oper[0], InstrSinceLastMod);
End;
Ch_Mop1:
CurProp^.ModifyOp(p^.oper[0], InstrSinceLastMod);
Ch_Wop2..Ch_RWop2:
Begin
If (InstrProp.Ch[Cnt] = Ch_RWop2) Then
CurProp^.ReadOp(p^.oper[1]);
CurProp^.DestroyOp(p^.oper[1], InstrSinceLastMod);
End;
Ch_Mop2:
CurProp^.ModifyOp(p^.oper[1], InstrSinceLastMod);
Ch_Wop3..Ch_RWop3:
Begin
If (InstrProp.Ch[Cnt] = Ch_RWop3) Then
CurProp^.ReadOp(p^.oper[2]);
CurProp^.DestroyOp(p^.oper[2], InstrSinceLastMod);
End;
Ch_Mop3:
CurProp^.ModifyOp(p^.oper[2], InstrSinceLastMod);
Ch_WMemEDI:
Begin
CurProp^.ReadReg(R_EDI);
FillChar(TmpRef, SizeOf(TmpRef), 0);
TmpRef.Base := R_EDI;
CurProp^.DestroyRefs(TmpRef, R_NO, InstrSinceLastMod)
End;
Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU:;
Else CurProp^.DestroyAllRegs(InstrSinceLastMod)
End;
Inc(Cnt)
End
End
End
End;
Function TAOptDFACpu.RegReadByInstr(Reg: TRegister; p: Pai): Boolean;
Var Cnt: AWord;
InstrProp: TInsProp;
TmpResult: Boolean;
Begin
TmpResult := False;
If (p^.typ = ait_instruction) Then
Case PInstr(p)^.opcode of
A_IMUL:
With PInstr(p)^ Do
TmpResult :=
RegInOp(Reg,oper[0]) or
RegInOp(Reg,oper[1]) or
((ops = 1) and
(reg = R_EAX));
A_DIV, A_IDIV, A_MUL:
With PInstr(p)^ Do
TmpResult :=
RegInOp(Reg,oper[0]) or
(Reg = R_EAX) or
((Reg = R_EDX) and
((opcode = A_DIV) or
(opcode = A_IDIV)) and
(opsize = S_L))
Else
Begin
Cnt := 1;
InstrProp := InsProp[PInstr(p)^.OpCode];
While (Cnt <= MaxCh) And
(InstrProp.Ch[Cnt] <> Ch_None) And
Not(TmpResult) Do
Begin
Case InstrProp.Ch[Cnt] Of
Ch_REAX..Ch_REDI,Ch_RWEAX..Ch_RWEDI
,Ch_MEAX..Ch_MEDI
TmpResult := Reg = TCh2Reg(InstrProp.Ch[Cnt]);
Ch_ROp1,Ch_RWOp1,Ch_Mop1:
TmpResult := RegInOp(Reg,PInstr(p)^.oper[0]);
Ch_ROp2,Ch_RWOp2,Ch_Mop2:
TmpResult := RegInOp(Reg,PInstr(p)^.oper[1]);
Ch_ROp3,Ch_RWOp3,Ch_Mop3:
TmpResult := RegInOp(Reg,PInstr(p)^.oper[2]);
Ch_WOp1: TmpResult := (PInstr(p)^.oper[0].typ = top_ref) And
RegInRef(Reg,PInstr(p)^.oper[0].ref^);
Ch_WOp2: TmpResult := (PInstr(p)^.oper[1].typ = top_ref) And
RegInRef(Reg,PInstr(p)^.oper[1].ref^);
Ch_WOp3: TmpResult := (PInstr(p)^.oper[2].typ = top_ref) And
RegInRef(Reg,PInstr(p)^.oper[2].ref^);
Ch_WMemEDI: TmpResult := (Reg = R_EDI);
Ch_FPU: TmpResult := Reg in [R_ST..R_ST7,R_MM0..R_MM7]
End;
Inc(Cnt)
End
End
End;
RegReadByInstr := TmpResult
End;
Function TAOptDFACpu.TCh2Reg(Ch: TInsChange): TRegister;
Begin
If (Ch <= Ch_REDI) Then
TCh2Reg := TRegister(Byte(Ch))
Else
If (Ch <= Ch_WEDI) Then
TCh2Reg := TRegister(Byte(Ch) - Byte(Ch_REDI))
Else
If (Ch <= Ch_RWEDI) Then
TCh2Reg := TRegister(Byte(Ch) - Byte(Ch_WEDI))
Else
If (Ch <= Ch_MEDI) Then
TCh2Reg := TRegister(Byte(Ch) - Byte(Ch_RWEDI))
End;
End.
{
$Log$
Revision 1.3 2002-09-07 15:25:14 peter
* old logs removed and tabs fixed
}