aoptcpu.pas 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. {
  2. $Id$
  3. Copyright (c) 1999 by Jonas Maebe, member of the Free Pascal
  4. Development Team
  5. This unit implements the i386 optimizer object
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. Unit aoptcpu;
  20. Interface
  21. uses cpubase, aoptobj, aoptcpub;
  22. Type
  23. TRegInfoCpu = Object(TRegInfo)
  24. Procedure AddReg(OldReg, NewReg: TRegister); Virtual;
  25. End;
  26. Type
  27. TAOptCpu = Object(TAoptObj)
  28. { uses the same constructor as TAopObj }
  29. Function RegMaxSize(Reg: TRegister): TRegister; Virtual;
  30. Function RegsSameSize(Reg1, Reg2: TRegister): Boolean; Virtual;
  31. Function IsLoadInstr(p: pai): Boolean; Virtual;
  32. Function IsStoreInstr(p: pai): Boolean; Virtual;
  33. Function TCh2Reg(Ch: TChange): TRegister; Virtual;
  34. Function RegReadByInstrCPU(Reg: TRegister; p: Pai); Virtual;
  35. End;
  36. Implementation
  37. {*********************** TAoptCpu **************************}
  38. Function TAOptCpu.RegMaxSize(Reg: TRegister): TRegister;
  39. Begin
  40. RegMaxSize := Reg;
  41. If (Reg >= R_AX)
  42. Then
  43. If (Reg <= R_DI)
  44. Then RegMaxSize := Reg16ToReg32(Reg)
  45. Else
  46. If (Reg <= R_BL)
  47. Then RegMaxSize := Reg8toReg32(Reg)
  48. End;
  49. Function TAOptCpu.RegsSameSize(Reg1, Reg2: TRegister): Boolean;
  50. Begin
  51. If (Reg1 <= R_EDI)
  52. Then RegsSameSize := (Reg2 <= R_EDI)
  53. Else
  54. If (Reg1 <= R_DI)
  55. Then RegsSameSize := (Reg2 in [R_AX..R_DI])
  56. Else
  57. If (Reg1 <= R_BL)
  58. Then RegsSameSize := (Reg2 in [R_AL..R_BL])
  59. Else RegsSameSize := False
  60. End;
  61. Function TAOptCpu.IsLoadInstr(p: pai): Boolean;
  62. Begin
  63. IsLoadInstr :=
  64. (p^.typ = ait_instruction) and
  65. ((PInstr(p)^.OpCode = A_MOV) or
  66. (PInstr(p)^.OpCode = A_MOVZX) or
  67. (PInstr(p)^.OpCode = A_MOVSX)) And
  68. (PInstr(p)^.oper[LoadSrc].typ = top_ref));
  69. End;
  70. Function TAOptCpu.IsStoreInstr(p: pai): Boolean;
  71. Begin
  72. IsLoadInstr :=
  73. (p^.typ = ait_instruction) and
  74. ((PInstr(p)^.OpCode = A_MOV) or
  75. (PInstr(p)^.OpCode = A_MOVZX) or
  76. (PInstr(p)^.OpCode = A_MOVSX)) And
  77. (PInstr(p)^.oper[StoreDst].typ = top_ref));
  78. End;
  79. Function TAOptCpu.TCh2Reg(Ch: TChange): TRegister;
  80. Begin
  81. If (Ch <= C_REDI) Then
  82. TCh2Reg := TRegister(Byte(Ch))
  83. Else
  84. If (Ch <= C_WEDI) Then
  85. TCh2Reg := TRegister(Byte(Ch) - Byte(C_REDI))
  86. Else
  87. If (Ch <= C_RWEDI) Then
  88. TCh2Reg := TRegister(Byte(Ch) - Byte(C_WEDI))
  89. Else InternalError($db)
  90. End;
  91. Function TAOptCpu.RegReadByInstr(Reg: TRegister; p: Pai);
  92. Var Cnt: AWord;
  93. InstrProp: TAsmInstrucProp;
  94. TmpResult: Boolean;
  95. Begin
  96. TmpResult := False;
  97. If (p^.typ = ait_instruction) Then
  98. Case p^.opcode of
  99. A_IMUL:
  100. With PInstr(p)^ Do
  101. TmpResult :=
  102. RegInOp(Reg,op[0]) or
  103. RegInOp(Reg,op[1]) or
  104. ((ops = 1) and
  105. (reg = R_EAX]))
  106. A_DIV, A_IDIV, A_MUL:
  107. TmpResult :=
  108. RegInOp(Reg,op[0]) or
  109. (Reg = R_EAX) or
  110. ((Reg = R_EDX) and
  111. ((p^.opcode = A_DIV) or
  112. (p^.opcode = A_IDIV)) and
  113. (p^.size = S_L))
  114. Else
  115. Begin
  116. Cnt := 1;
  117. InstrProp := AsmInstr[PInstr(p)^.OpCode);
  118. While (Cnt <= MaxCh) And
  119. (InstrProp.Ch[Cnt] <> C_None) And
  120. Not(TmpResult) Do
  121. Begin
  122. Case InstrProp.Ch[Cnt] Of
  123. C_REAX..C_REDI,C_RWEAX..C_RWEDI
  124. {$ifdef arithopt}
  125. ,C_MEAX..C_MEDI
  126. {$endif arithopt}:
  127. TmpResult := Reg = TCh2Reg(InstrProp.Ch[Cnt]);
  128. C_ROp1,C_RWOp1{$ifdef arithopt},C_Mop1{$endif arithopt}:
  129. TmpResult := RegInOp(PInstr(p)^.oper[0]);
  130. C_ROp2,C_RWOp2{$ifdef arithopt},C_Mop2{$endif arithopt}:
  131. TmpResult := RegInOp(PInstr(p)^.oper[1]);
  132. C_ROp3,C_RWOp3{$ifdef arithopt},C_Mop3{$endif arithopt}:
  133. TmpResult := RegInOp(PInstr(p)^.oper[2]);
  134. C_WOp1: TmpResult := (PInstr^.oper[0].typ = top_ref) And
  135. (RegInRef(Reg,PInstr^.oper[0].ref);
  136. C_WOp2: TmpResult := (PInstr^.oper[0].typ = top_ref) And
  137. (RegInRef(Reg,PInstr^.oper[0].ref);
  138. C_WOp3: TmpResult := (PInstr^.oper[0].typ = top_ref) And
  139. (RegInRef(Reg,PInstr^.oper[0].ref);
  140. C_WMemEDI: TmpResult := (Reg = R_EDI);
  141. C_FPU: TmpResult := Reg in [R_ST..R_ST7,R_MM0..R_MM7]
  142. End;
  143. Inc(Cnt)
  144. End
  145. End
  146. End
  147. End;
  148. { ********************* TRegInfoCpu *****************}
  149. Procedure TRegInfoCpu.AddReg(OldReg, NewReg: TRegister);
  150. Begin
  151. NewRegsEncountered := NewRegsEncountered + [NewReg];
  152. OldRegsEncountered := OldRegsEncountered + [OldReg];
  153. New2OldReg[NewReg] := OldReg;
  154. Case OldReg Of
  155. R_EAX..R_EDI:
  156. Begin
  157. NewRegsEncountered := NewRegsEncountered + [Reg32toReg16(NewReg)];
  158. OldRegsEncountered := OldRegsEncountered + [Reg32toReg16(OldReg)];
  159. New2OldReg[Reg32toReg16(NewReg)] := Reg32toReg16(OldReg);
  160. If (NewReg in [R_EAX..R_EBX]) And
  161. (OldReg in [R_EAX..R_EBX]) Then
  162. Begin
  163. NewRegsEncountered := NewRegsEncountered + [Reg32toReg8(NewReg)];
  164. OldRegsEncountered := OldRegsEncountered + [Reg32toReg8(OldReg)];
  165. New2OldReg[Reg32toReg8(NewReg)] := Reg32toReg8(OldReg);
  166. End;
  167. End;
  168. R_AX..R_DI:
  169. Begin
  170. NewRegsEncountered := NewRegsEncountered + [Reg16toReg32(NewReg)];
  171. OldRegsEncountered := OldRegsEncountered + [Reg16toReg32(OldReg)];
  172. New2OldReg[Reg16toReg32(NewReg)] := Reg16toReg32(OldReg);
  173. If (NewReg in [R_AX..R_BX]) And
  174. (OldReg in [R_AX..R_BX]) Then
  175. Begin
  176. NewRegsEncountered := NewRegsEncountered + [Reg16toReg8(NewReg)];
  177. OldRegsEncountered := OldRegsEncountered + [Reg16toReg8(OldReg)];
  178. New2OldReg[Reg16toReg8(NewReg)] := Reg16toReg8(OldReg);
  179. End;
  180. End;
  181. R_AL..R_BL:
  182. Begin
  183. NewRegsEncountered := NewRegsEncountered + [Reg8toReg32(NewReg)]
  184. + [Reg8toReg16(NewReg)];
  185. OldRegsEncountered := OldRegsEncountered + [Reg8toReg32(OldReg)]
  186. + [Reg8toReg16(OldReg)];
  187. New2OldReg[Reg8toReg32(NewReg)] := Reg8toReg32(OldReg);
  188. End;
  189. End;
  190. End;
  191. End.
  192. {
  193. $Log$
  194. Revision 1.4 1999-08-11 14:23:39 jonas
  195. * some fixes to RegReadByInstr
  196. Revision 1.3 1999/08/10 12:40:20 jonas
  197. + implemented RegReadByInstr
  198. Revision 1.1 1999/08/08 13:24:50 jonas
  199. + added copyright header/GNU license info
  200. * made the assembler optimizer almost completely OOP
  201. * some code style clean up and extra comments
  202. * moved from the new/aopt to the /new and /new/i386 dirs
  203. }