{ $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 }