2
0

aopt386.inc 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl and Jonas Maebe
  4. This include file contains the reloading optimizer for i386+
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {$Define OptimizeMovs}
  19. Procedure ReloadOpt(AsmL: PaasmOutput);
  20. Const MaxCh = 3;
  21. {content types}
  22. con_Unknown = 0;
  23. con_ref = 1;
  24. con_const = 2;
  25. con_symbol = 3;
  26. Type TChange = (C_None,
  27. C_EAX, C_ECX, C_EDX, C_EBX, C_ESP, C_EBP, C_ESI, C_EDI,
  28. C_CDirFlag, C_SDirFlag, C_Flags, C_FPU,
  29. C_Op1, C_Op2, C_Op3,
  30. C_MemEDI);
  31. TFlagContents = (F_Unknown, F_NotSet, F_Set);
  32. TAsmInstrucProp = Record
  33. NCh: Byte;
  34. Ch: Array[1..MaxCh] of TChange;
  35. End;
  36. TContent = Record
  37. StartMod: Pointer; {start and end of block instructions that defines the
  38. content of this register; If Typ = con_const, then
  39. Longint(StartMod) = value of the constant)}
  40. State: Word; {starts at 0, gets increased everytime the register is modified}
  41. NrOfMods: Byte;
  42. { ModReg: TRegister; }{if one register gets a block assigned from an other register,
  43. this variable holds the name of that register (so it can be
  44. substituted when checking the block afterwards)}
  45. Typ: Byte; {con_*}
  46. { CanBeDestroyed: Boolean;} {if it's a register modified by the optimizer}
  47. End;
  48. TRegContent = Array[R_NO..R_EDI] Of TContent;
  49. TRegFPUContent = Array[R_ST..R_ST7] Of TContent;
  50. TPaiProp = Record
  51. Regs: TRegContent;
  52. { FPURegs: TRegFPUContent;} {currently not yet used}
  53. LineSave: Longint;
  54. DirFlag: TFlagContents;
  55. {can this instruction be removed?}
  56. CanBeRemoved: Boolean;
  57. End;
  58. PPaiProp = ^TPaiProp;
  59. {$IfDef TP}
  60. TPaiPropBlock = Array[1..(65520 div (((SizeOf(TPaiProp)+1)div 2)*2))] Of TPaiProp;
  61. {$else}
  62. TPaiPropBlock = Array[1..250000] Of TPaiProp;
  63. {$EndIf TP}
  64. PPaiPropBlock = ^TPaiPropBlock;
  65. Const AsmInstr: Array[tasmop] Of TAsmInstrucProp = (
  66. {MOV} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  67. {MOVZX} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  68. {MOVSX} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  69. {LABEL} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  70. {ADD} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  71. {CALL} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  72. {IDIV} (NCh: 3; Ch: (C_EAX, C_EDX, C_Flags)),
  73. {IMUL} (NCh: 3; Ch: (C_EAX, C_EDX, C_Flags)), {handled separately, because several forms exist}
  74. {JMP} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  75. {LEA} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  76. {MUL} (NCh: 3; Ch: (C_EAX, C_EDX, C_Flags)),
  77. {NEG} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  78. {NOT} (NCh: 2; Ch: (C_Op1, C_Flags, C_None)),
  79. {POP} (NCh: 2; Ch: (C_Op1, C_ESP, C_None)),
  80. {POPAD} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  81. {PUSH} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  82. {PUSHAD} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  83. {RET} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  84. {SUB} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  85. {XCHG} (NCh: 2; Ch: (C_Op1, C_Op2, C_None)), {(will be) handled seperately}
  86. {XOR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  87. {FILD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  88. {CMP} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  89. {JZ} (NCh: 0; Ch: (C_None, C_None, C_None)),
  90. {INC} (NCh: 2; Ch: (C_Op1, C_Flags, C_None)),
  91. {DEC} (NCh: 2; Ch: (C_Op1, C_Flags, C_None)),
  92. {SETE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  93. {SETNE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  94. {SETL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  95. {SETG} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  96. {SETLE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  97. {SETGE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  98. {JE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  99. {JNE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  100. {JL} (NCh: 0; Ch: (C_None, C_None, C_None)),
  101. {JG} (NCh: 0; Ch: (C_None, C_None, C_None)),
  102. {JLE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  103. {JGE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  104. {OR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  105. {FLD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  106. {FADD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  107. {FMUL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  108. {FSUB} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  109. {FDIV} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  110. {FCHS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  111. {FLD1} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  112. {FIDIV} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  113. {CLTD} (NCh: 1; Ch: (C_EDX, C_None, C_None)),
  114. {JNZ} (NCh: 0; Ch: (C_None, C_None, C_None)),
  115. {FSTP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  116. {AND} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  117. {JNO} (NCh: 0; Ch: (C_None, C_None, C_None)),
  118. {NOTH} (NCh: 0; Ch: (C_None, C_None, C_None)), {***???***}
  119. {NONE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  120. {ENTER} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  121. {LEAVE} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  122. {CLD} (NCh: 1; Ch: (C_CDirFlag, C_None, C_None)),
  123. {MOVS} (NCh: 3; Ch: (C_ESI, C_EDI, C_MemEDI)),
  124. {REP} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
  125. {SHL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  126. {SHR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  127. {BOUND} (NCh: 0; Ch: (C_None, C_None, C_None)),
  128. {JNS} (NCh: 0; Ch: (C_None, C_None, C_None)),
  129. {JS} (NCh: 0; Ch: (C_None, C_None, C_None)),
  130. {JO} (NCh: 0; Ch: (C_None, C_None, C_None)),
  131. {SAR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  132. {TEST} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  133. {FCOM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  134. {FCOMP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  135. {FCOMPP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  136. {FXCH} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  137. {FADDP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  138. {FMULP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  139. {FSUBP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  140. {FDIVP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  141. {FNSTS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  142. {SAHF} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  143. {FDIVRP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  144. {FSUBRP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  145. {SETC} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  146. {SETNC} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  147. {JC} (NCh: 0; Ch: (C_None, C_None, C_None)),
  148. {JNC} (NCh: 0; Ch: (C_None, C_None, C_None)),
  149. {JA} (NCh: 0; Ch: (C_None, C_None, C_None)),
  150. {JAE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  151. {JB} (NCh: 0; Ch: (C_None, C_None, C_None)),
  152. {JBE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  153. {SETA} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  154. {SETAE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  155. {SETB} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  156. {SETBE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  157. {AAA} (NCh: 2; Ch: (C_EAX, C_Flags, C_None)),
  158. {AAD} (NCh: 2; Ch: (C_EAX, C_Flags, C_None)),
  159. {AAM} (NCh: 2; Ch: (C_EAX, C_Flags, C_None)),
  160. {AAS} (NCh: 2; Ch: (C_EAX, C_Flags, C_None)),
  161. {CBW} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  162. {CDQ} (NCh: 2; Ch: (C_EAX, C_EDX, C_None)),
  163. {CLC} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  164. {CLI} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  165. {CLTS} (NCh: 0; Ch: (C_None, C_None, C_None)),
  166. {CMC} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  167. {CWD} (NCh: 2; Ch: (C_EAX, C_EDX, C_None)),
  168. {CWDE} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  169. {DAA} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  170. {DAS} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  171. {HLT} (NCh: 0; Ch: (C_None, C_None, C_None)),
  172. {IRET} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  173. {LAHF} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  174. {LODS} (NCh: 2; Ch: (C_EAX, C_ESI, C_None)),
  175. {LOCK} (NCh: 0; Ch: (C_None, C_None, C_None)),
  176. {NOP} (NCh: 0; Ch: (C_None, C_None, C_None)),
  177. {PUSHA} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  178. {PUSHF} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  179. {PUSHFD} (NCh: 1; Ch: (C_ESP, C_None, C_None)),
  180. {STC} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  181. {STD} (NCh: 1; Ch: (C_SDirFlag, C_None, C_None)),
  182. {STI} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  183. {STOS} (NCh: 2; Ch: (C_MemEDI, C_EDI, C_None)),
  184. {WAIT} (NCh: 0; Ch: (C_None, C_None, C_None)),
  185. {XLAT} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  186. {XLATB} (NCh: 1; Ch: (C_EAX, C_None, C_None)),
  187. {MOVSB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  188. {MOVSBL} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  189. {MOVSBW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  190. {MOVSWL} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  191. {MOVZB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  192. {MOVZWL} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  193. {POPA} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  194. {IN} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  195. {OUT} (NCh: 0; Ch: (C_None, C_None, C_None)),
  196. {LDS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
  197. {LCS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
  198. {LES} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
  199. {LFS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
  200. {LGS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
  201. {LSS} (NCh: 2; Ch: (C_Op2, C_None, C_None)),
  202. {POPF} (NCh: 2; Ch: (C_Flags, C_ESP, C_None)),
  203. {SBB} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  204. {ADC} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  205. {DIV} (NCh: 3; Ch: (C_EAX, C_EDX, C_Flags)),
  206. {ROR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  207. {ROL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  208. {RCL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  209. {RCR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  210. {SAL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  211. {SHLD} (NCh: 2; Ch: (C_Op3, C_Flags, C_None)),
  212. {SHRD} (NCh: 2; Ch: (C_Op3, C_Flags, C_None)),
  213. {LCALL} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  214. {LJMP} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  215. {LRET} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  216. {JNAE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  217. {JNB} (NCh: 0; Ch: (C_None, C_None, C_None)),
  218. {JNA} (NCh: 0; Ch: (C_None, C_None, C_None)),
  219. {JNBE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  220. {JP} (NCh: 0; Ch: (C_None, C_None, C_None)),
  221. {JNP} (NCh: 0; Ch: (C_None, C_None, C_None)),
  222. {JPE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  223. {JPO} (NCh: 0; Ch: (C_None, C_None, C_None)),
  224. {JNGE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  225. {JNG} (NCh: 0; Ch: (C_None, C_None, C_None)),
  226. {JNL} (NCh: 0; Ch: (C_None, C_None, C_None)),
  227. {JNLE} (NCh: 0; Ch: (C_None, C_None, C_None)),
  228. {JCXZ} (NCh: 0; Ch: (C_None, C_None, C_None)),
  229. {JECXZ} (NCh: 0; Ch: (C_None, C_None, C_None)),
  230. {LOOP} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
  231. {CMPS} (NCh: 3; Ch: (C_ESI, C_EDI, C_Flags)),
  232. {INS} (NCh: 1; Ch: (C_EDI, C_None, C_None)),
  233. {OUTS} (NCh: 1; Ch: (C_ESI, C_None, C_None)),
  234. {SCAS} (NCh: 2; Ch: (C_EDI, C_Flags, C_None)),
  235. {BSF} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  236. {BSR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  237. {BT} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  238. {BTC} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  239. {BTR} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  240. {BTS} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  241. {INT} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  242. {INT3} (NCh: 0; Ch: (C_None, C_None, C_None)),
  243. {INTO} (NCh: 255; Ch: (C_None, C_None, C_None)), {don't know value of any register}
  244. {BOUNDL} (NCh: 0; Ch: (C_None, C_None, C_None)),
  245. {BOUNDW} (NCh: 0; Ch: (C_None, C_None, C_None)),
  246. {LOOPZ} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
  247. {LOOPE} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
  248. {LOOPNZ} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
  249. {LOOPNE} (NCh: 1; Ch: (C_ECX, C_None, C_None)),
  250. {SETO} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  251. {SETNO} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  252. {SETNAE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  253. {SETNB} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  254. {SETZ} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  255. {SETNZ} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  256. {SETNA} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  257. {SETNBE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  258. {SETS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  259. {SETNS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  260. {SETP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  261. {SETPE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  262. {SETNP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  263. {SETPO} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  264. {SETNGE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  265. {SETNL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  266. {SETNG} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  267. {SETNLE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  268. {ARPL} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  269. {LAR} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  270. {LGDT} (NCh: 0; Ch: (C_None, C_None, C_None)),
  271. {LIDT} (NCh: 0; Ch: (C_None, C_None, C_None)),
  272. {LLDT} (NCh: 0; Ch: (C_None, C_None, C_None)),
  273. {LMSW} (NCh: 0; Ch: (C_None, C_None, C_None)),
  274. {LSL} (NCh: 2; Ch: (C_Op2, C_Flags, C_None)),
  275. {LTR} (NCh: 0; Ch: (C_None, C_None, C_None)),
  276. {SGDT} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  277. {SIDT} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  278. {SLDT} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  279. {SMSW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  280. {STR} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  281. {VERR} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  282. {VERW} (NCh: 1; Ch: (C_Flags, C_None, C_None)),
  283. {FABS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  284. {FBLD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  285. {FBSTP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  286. {FCLEX} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  287. {FNCLEX} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  288. {FCOS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  289. {FDECSTP}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  290. {FDISI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  291. {FNDISI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  292. {FDIVR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  293. {FENI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  294. {FNENI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  295. {FFREE} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  296. {FIADD} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  297. {FICOM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  298. {FICOMP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  299. {FIDIVR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  300. {FIMUL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  301. {FINCSTP}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  302. {FINIT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  303. {FNINIT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  304. {FIST} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  305. {FISTP} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  306. {FISUB} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  307. {FSUBR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  308. {FLDCW} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  309. {FLDENV} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  310. {FLDLG2} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  311. {FLDLN2} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  312. {FLDL2E} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  313. {FLDL2T} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  314. {FLDPI} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  315. {FLDS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  316. {FLDZ} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  317. {FNOP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  318. {FPATAN} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  319. {FPREM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  320. {FPREM1} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  321. {FPTAN} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  322. {FRNDINT}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  323. {FRSTOR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  324. {FSAVE} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  325. {FNSAVE} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  326. {FSCALE} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  327. {FSETPM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  328. {FSIN} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  329. {FSINCOS}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  330. {FSQRT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  331. {FST} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  332. {FSTCW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  333. {FNSTCW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  334. {FSTENV} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  335. {FNSTENV}(NCh: 1; Ch: (C_Op1, C_None, C_None)),
  336. {FSTSW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  337. {FNSTSW} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  338. {FTST} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  339. {FUCOM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  340. {FUCOMP} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  341. {FUCOMPP}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  342. {FWAIT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  343. {FXAM} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  344. {FXTRACT}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  345. {FYL2X} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  346. {FYL2XP1}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  347. {F2XM1} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  348. {FILDQ} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  349. {FILDS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  350. {FILDL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  351. {FLDL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  352. {FLDT} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  353. {FISTQ} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  354. {FISTS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  355. {FISTL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  356. {FSTL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  357. {FSTS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  358. {FSTPS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  359. {FISTPL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  360. {FSTPL} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  361. {FISTPS} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  362. {FISTPQ} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  363. {FSTPT} (NCh: 1; Ch: (C_Op1, C_None, C_None)),
  364. {FCOMPS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  365. {FICOMPL}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  366. {FCOMPL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  367. {FICOMPS}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  368. {FCOMS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  369. {FICOML} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  370. {FCOML} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  371. {FICOMS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  372. {FIADDL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  373. {FADDL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  374. {FIADDS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  375. {FISUBL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  376. {FSUBL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  377. {FISUBS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  378. {FSUBS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  379. {FSUBR} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  380. {FSUBRS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  381. {FISUBRL}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  382. {FSUBRL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  383. {FISUBRS}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  384. {FMULS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  385. {FIMUL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  386. {FMULL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  387. {FIMULS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  388. {FIDIVS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  389. {FIDIVL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  390. {FDIVL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  391. {FIDIVS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  392. {FDIVRS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  393. {FIDIVRL}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  394. {FDIVRL} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  395. {FIDIVRS}(NCh: 1; Ch: (C_FPU, C_None, C_None)),
  396. {REPE} (NCh: 0; Ch: (C_ECX, C_None, C_None)),
  397. {REPNE} (NCh: 0; Ch: (C_ECX, C_None, C_None)),
  398. {FADDS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  399. {POPFD} (NCh: 2; Ch: (C_ESP, C_Flags, C_None)),
  400. {below are the MMX instructions}
  401. {A_EMMS} (NCh: 1; Ch: (C_FPU, C_None, C_None)),
  402. {A_MOVD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  403. {A_MOVQ} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  404. {A_PACKSSDW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  405. {A_PACKSSWB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  406. {A_PACKUSWB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  407. {A_PADDB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  408. {A_PADDD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  409. {A_PADDSB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  410. {A_PADDSW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  411. {A_PADDUSB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  412. {A_PADDUSW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  413. {A_PADDW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  414. {A_PAND} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  415. {A_PANDN} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  416. {A_PCMPEQB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  417. {A_PCMPEQD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  418. {A_PCMPEQW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  419. {A_PCMPGTB} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  420. {A_PCMPGTD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  421. {A_PCMPGTW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  422. {A_PMADDWD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  423. {A_PMULHW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  424. {A_PMULLW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  425. {A_POR} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  426. {A_PSLLD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  427. {A_PSLLQ} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  428. {A_PSLLW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  429. {A_PSRAD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  430. {A_PSRAW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  431. {A_PSRLD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  432. {A_PSRLQ} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  433. {A_PSRLW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  434. {A_PSUBB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  435. {A_PSUBD} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  436. {A_PSUBSB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  437. {A_PSUBSW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  438. {A_PSUBUSB} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  439. {A_PSUBUSW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  440. {A_PSUBW} (NCh: 1; Ch: (C_Op2, C_None, C_None)),
  441. {A_PUNPCKHBW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  442. {A_PUNPCKHDQ} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  443. {A_PUNPCKHWD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  444. {A_PUNPCKLBW} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  445. {A_PUNPCKLDQ} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  446. {A_PUNPCKLWD} (NCh: 255; Ch: (C_FPU, C_None, C_None)),
  447. {A_PXOR} (NCh: 1; Ch: (C_Op2, C_None, C_None)));
  448. Var NrOfPaiObjs, NrOfPaiFast: Longint;
  449. PaiPropBlock: PPaiPropBlock;
  450. NrOfInstrSinceLastMod: Array[R_EAX..R_EDI] Of Byte;
  451. Function TCh2Reg(Ch: TChange): TRegister;
  452. {converts a TChange variable to a TRegister}
  453. Begin
  454. If (CH <= C_EDI)
  455. Then TCh2Reg := TRegister(Byte(Ch))
  456. Else InternalError($db)
  457. End;
  458. Procedure DestroyReg(p1: pai; Reg: TRegister);
  459. {Destroys the contents of the register Reg in the PPaiProp of P}
  460. Var TmpState: Longint;
  461. Begin
  462. Reg := Reg32(Reg);
  463. NrOfInstrSinceLastMod[Reg] := 0;
  464. If (Reg >= R_EAX) And (Reg <= R_EDI)
  465. Then
  466. Begin
  467. TmpState := PPaiProp(p1^.fileinfo.line)^.Regs[Reg].State+1;
  468. FillChar(PPaiProp(p1^.fileinfo.line)^.Regs[Reg], SizeOf(TContent), 0);
  469. PPaiProp(p1^.fileinfo.line)^.Regs[Reg].State := TmpState;
  470. End;
  471. End;
  472. (*Function FindZeroreg(p: Pai; Var Result: TRegister): Boolean;
  473. {Finds a register which contains the constant zero}
  474. Var Counter: TRegister;
  475. Begin
  476. Counter := R_EAX;
  477. FindZeroReg := True;
  478. While (Counter <= R_EDI) And
  479. ((PPaiProp(p^.fileinfo.line)^.Regs[Counter].Typ <> Con_Const) or
  480. (PPaiProp(p^.fileinfo.line)^.Regs[Counter].StartMod <> Pointer(0))) Do
  481. Inc(Byte(Counter));
  482. If (PPaiProp(p^.fileinfo.line)^.Regs[Counter].Typ = Con_Const) And
  483. (PPaiProp(p^.fileinfo.line)^.Regs[Counter].StartMod = Pointer(0))
  484. Then Result := Counter
  485. Else FindZeroReg := False;
  486. End;*)
  487. Procedure DestroyRefs(p: pai; Const Ref: TReference; WhichRegNot: TRegister);
  488. {destroys all registers which possibly contain a reference to Ref}
  489. Var Counter: TRegister;
  490. Begin
  491. WhichRegNot := Reg32(WhichRegNot);
  492. If (Ref.base <> R_NO) Or
  493. (Ref.index <> R_NO)
  494. Then
  495. Begin
  496. If (Ref.base = ProcInfo.FramePointer)
  497. Then
  498. {write something to a parameter or a local variable}
  499. For Counter := R_EAX to R_EDI Do
  500. With PPaiProp(p^.fileinfo.line)^.Regs[Counter] Do
  501. Begin
  502. If (Counter <> WhichRegNot) And
  503. (typ = Con_Ref) And
  504. (Pai(StartMod)^.typ = ait_instruction) And
  505. (Pai386(StartMod)^.op1t = top_ref) And
  506. (RefsEqual(TReference(Pai386(StartMod)^.op1^), Ref) Or
  507. (Not(cs_UncertainOpts in AktSwitches) And
  508. (NrOfMods <> 1)))
  509. Then DestroyReg(p, Counter)
  510. End
  511. Else
  512. {writing something to a pointer location}
  513. For Counter := R_EAX to R_EDI Do
  514. With PPaiProp(p^.fileinfo.line)^.Regs[Counter] Do
  515. If (Counter <> WhichRegNot) And
  516. (typ = Con_Ref) And
  517. (Not(cs_UncertainOpts in AktSwitches) Or
  518. (Ref.Base = R_EDI) Or
  519. (Not((NrOfMods = 1) And
  520. (Pai(StartMod)^.typ = ait_instruction) And
  521. (Pai386(StartMod)^.op1t = top_ref) And
  522. (PReference(Pai386(StartMod)^.op1)^.base = ProcInfo.FramePointer))))
  523. Then
  524. DestroyReg(p, Counter) {we don't know what memory location the reference points to,
  525. so we just destroy every register which contains a memory
  526. reference}
  527. End
  528. Else {the ref is a var name or we just have a reference an absolute offset}
  529. Begin
  530. For Counter := R_EAX to R_EDI Do
  531. If (Counter <> WhichRegNot) And
  532. (PPaiProp(p^.fileinfo.line)^.Regs[Counter].typ = Con_Ref) And
  533. (Not(cs_UncertainOpts in AktSwitches) Or
  534. RefsEqual(Ref,
  535. TReference(Pai386(PPaiProp(p^.fileinfo.line)^.Regs[Counter].StartMod)^.op1^))) Then
  536. DestroyReg(p, Counter)
  537. End;
  538. End;
  539. {$IfDef OptimizeMovs}
  540. Function OpsEqual(typ: Longint; op1, op2: Pointer): Boolean;
  541. Begin {checks whether the two ops are equal}
  542. Case typ Of
  543. Top_Reg, Top_Const: OpsEqual := op1 = op2;
  544. Top_Ref: OpsEqual := RefsEqual(TReference(op1^), TReference(op2^));
  545. Top_None: OpsEqual := True
  546. Else OpsEqual := False
  547. End;
  548. End;
  549. Function RegsSameContent(p1, p2: Pai; Reg: TRegister): Boolean;
  550. {checks whether Reg has the same content in the PPaiProp of p1 and p2}
  551. Begin
  552. Reg := Reg32(Reg);
  553. RegsSameContent :=
  554. PPaiProp(p1^.fileinfo.line)^.Regs[Reg].State =
  555. PPaiProp(p2^.fileinfo.line)^.Regs[Reg].State;
  556. End;
  557. Function InstructionsEqual(p1, p2: Pai): Boolean;
  558. Begin {checks whether two Pai386 instructions are equal}
  559. InstructionsEqual :=
  560. Assigned(p1) And Assigned(p2) And
  561. {$ifdef regalloc}
  562. ((((Pai(p1)^.typ = ait_regalloc) And
  563. (Pai(p2)^.typ = ait_regalloc)) Or
  564. ((Pai(p1)^.typ = ait_regdealloc) And
  565. (Pai(p2)^.typ = ait_regdealloc))) And
  566. (PaiRegAlloc(p1)^.reg = PaiRegAlloc(p2)^.reg)) Or
  567. {$endif regalloc}
  568. ((Pai(p1)^.typ = ait_instruction) And
  569. (Pai(p1)^.typ = ait_instruction) And
  570. (Pai386(p1)^._operator = Pai386(p2)^._operator) And
  571. (Pai386(p1)^.op1t = Pai386(p2)^.op1t) And
  572. (Pai386(p1)^.op2t = Pai386(p2)^.op2t) And
  573. OpsEqual(Pai386(p1)^.op1t, Pai386(p1)^.op1, Pai386(p2)^.op1) And
  574. OpsEqual(Pai386(p1)^.op2t, Pai386(p1)^.op2, Pai386(p2)^.op2))
  575. End;
  576. Function CheckSequence(p: Pai; Reg: TRegister; Var Found: Longint): Boolean;
  577. {checks whether the current instruction sequence (starting with p) and the
  578. one between StartMod and EndMod of Reg are the same. If so, the number of
  579. instructions that match is stored in Found and true is returned, otherwise
  580. Found holds the number of instructions between StartMod and EndMod and false
  581. is returned}
  582. Var hp2, hp3, EndMod: Pai;
  583. TmpResult: Boolean;
  584. RegsNotYetChecked: Set Of TRegister;
  585. Counter: Byte;
  586. Function NoChangedRegInRef(oldp, newp: Pai): Boolean;
  587. Var TmpP: Pai;
  588. {checks if the first operator of newp is a reference and in that case checks
  589. whether that reference includes regs that have been changed since oldp. This
  590. to avoid wrong optimizations like
  591. movl 8(%epb), %eax movl 8(%epb), %eax
  592. movl 12(%epb), %edx movl 12(%epb), %edx
  593. movl (%eax,%edx,1), %edi movl (%eax,%edx,1), %edi
  594. pushl %edi being converted to pushl %edi
  595. movl 8(%epb), %eax movl 16(%ebp), %edx
  596. movl 16(%epb), %edx pushl %edi
  597. movl (%eax,%edx,1), %edi
  598. pushl %edi
  599. because first is checked whether %eax isn't changed (it isn't) and
  600. consequently all instructions containg %eax are removed}
  601. Begin
  602. TmpResult := True;
  603. If (Pai(oldp)^.typ = ait_instruction) Then {oldp and newp are the same instruction}
  604. Case Pai386(oldp)^.op1t Of
  605. Top_Reg:
  606. If (Reg32(TRegister(Pai386(oldp)^.op1)) in RegsNotYetChecked) Then
  607. Begin
  608. RegsNotYetChecked := RegsNotYetChecked - [Reg32(TRegister(Pai386(oldp)^.op1))];
  609. If Assigned(newp^.previous)
  610. Then
  611. Begin
  612. TmpP := Pai(newp^.previous);
  613. While Assigned (TmpP^.previous) And
  614. PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do
  615. TmpP := Pai(TmpP^.previous);
  616. TmpResult := Assigned(TmpP) And
  617. RegsSameContent(oldp, TmpP, Reg32(TRegister(Pai386(oldp)^.op1)))
  618. End
  619. Else TmpResult := False;
  620. End;
  621. Top_Ref:
  622. With TReference(Pai386(oldp)^.op1^) Do
  623. Begin
  624. If (Base in RegsNotYetChecked) And
  625. (Base <> R_NO) Then
  626. Begin
  627. RegsNotYetChecked := RegsNotYetChecked - [Base];
  628. If Assigned(newp^.previous)
  629. Then
  630. Begin
  631. TmpP := Pai(newp^.previous);
  632. While Assigned (TmpP^.previous) And
  633. PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do
  634. TmpP := Pai(TmpP^.previous);
  635. TmpResult := Assigned(TmpP) And
  636. RegsSameContent(oldp, TmpP, Base)
  637. End
  638. Else TmpResult := False;
  639. End;
  640. If TmpResult And
  641. (Index <> R_NO) And
  642. (Index in RegsNotYetChecked) Then
  643. Begin
  644. RegsNotYetChecked := RegsNotYetChecked - [Index];
  645. If Assigned(newp^.previous)
  646. Then
  647. Begin
  648. TmpP := Pai(newp^.previous);
  649. While Assigned (TmpP^.previous) And
  650. PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do
  651. TmpP := Pai(TmpP^.previous);
  652. TmpResult := Assigned(TmpP) And
  653. RegsSameContent(oldp, TmpP, Index)
  654. End
  655. Else TmpResult := False;
  656. End;
  657. End;
  658. End;
  659. NoChangedRegInRef := TmpResult;
  660. End;
  661. Begin {CheckSequence}
  662. Reg := Reg32(Reg);
  663. Found := 0;
  664. hp2 := PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].StartMod;
  665. hp3 := p;
  666. EndMod := PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].StartMod;
  667. RegsNotYetChecked := [R_EAX..R_EDI];
  668. For Counter := 2 to PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods Do
  669. EndMod := Pai(EndMod^.Next);
  670. While (Found <> PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods) And
  671. InstructionsEqual(hp2, hp3) And
  672. NoChangedRegInRef(EndMod, hp3) Do
  673. Begin
  674. hp2 := Pai(hp2^.next);
  675. hp3 := Pai(hp3^.next);
  676. Inc(Found)
  677. End;
  678. If (Found <> PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods)
  679. Then
  680. Begin
  681. If ((Found+1) = PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods) And
  682. Assigned(hp2) And
  683. (Pai(hp2)^.typ = ait_instruction) And
  684. (Pai386(hp2)^._operator In [A_MOV, A_MOVZX]) And
  685. (Pai386(hp2)^.op1t = top_ref) And
  686. (Pai386(hp2)^.op2t = top_reg) And
  687. Assigned(hp3) And
  688. (Pai(hp3)^.typ = ait_instruction) And
  689. (Pai386(hp3)^._operator In [A_MOV, A_MOVZX]) And
  690. (Pai386(hp3)^.op1t = top_ref) And
  691. (Pai386(hp3)^.op2t = top_reg) And
  692. (Pai386(hp2)^._operator <> Pai386(hp3)^._operator) And
  693. RefsEqual(TReference(Pai386(hp2)^.op1^),TReference(Pai386(hp3)^.op1^)) And
  694. NoChangedRegInRef(EndMod, hp3)
  695. Then
  696. If (Pai386(hp2)^._operator = A_MOV)
  697. Then
  698. Begin
  699. If (Pai386(hp2)^.Size = S_B) And
  700. (Reg8toReg32(TRegister(Pai386(hp2)^.op2)) =
  701. TRegister(Pai386(hp3)^.op2))
  702. Then
  703. Begin
  704. Pai386(hp2)^._operator := A_MOVZX;
  705. Pai386(hp2)^.op2 := Pai386(hp3)^.op2;
  706. Pai386(hp2)^.Size := S_BL;
  707. Inc(Found);
  708. CheckSequence := True;
  709. End
  710. Else
  711. Begin
  712. CheckSequence := False;
  713. If (Found > 0) Then
  714. Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
  715. End
  716. End
  717. Else
  718. Begin
  719. If (Pai386(hp3)^.Size = S_B) And
  720. (Reg8toReg32(TRegister(Pai386(hp3)^.op2)) =
  721. TRegister(Pai386(hp2)^.op2))
  722. Then
  723. Begin
  724. CheckSequence := True;
  725. Inc(Found)
  726. End
  727. Else
  728. Begin
  729. CheckSequence := False;
  730. If (Found > 0) Then
  731. Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
  732. End
  733. End
  734. Else
  735. Begin
  736. CheckSequence := False;
  737. If (found > 0) then
  738. {this is correct because we only need to turn off the CanBeRemoved flag
  739. when an instruction has already been processed by CheckSequence
  740. (otherwise CanBeRemoved can't be true, or can't have to be turned off).
  741. If it has already been processed by checkSequence and flagged to be
  742. removed, it means that it has been checked against a previous sequence
  743. and that it was equal (otherwise CheckSequence would have returned false
  744. and the instruction wouldn't have been removed). If this "If found > 0"
  745. check is left out, incorrect optimizations are performed.}
  746. Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
  747. End
  748. End
  749. Else CheckSequence := True;
  750. End; {CheckSequence}
  751. {$Endif OptimizeMovs}
  752. Procedure DestroyAllRegs(p: Pai);
  753. Var Counter: TRegister;
  754. Begin {initializes/desrtoys all registers}
  755. For Counter := R_EAX To R_EDI Do
  756. DestroyReg(p, Counter);
  757. PPaiProp(p^.fileinfo.line)^.DirFlag := F_Unknown;
  758. End;
  759. Procedure Destroy(PaiObj: Pai; opt: Longint; Op: Pointer);
  760. Begin
  761. Case opt Of
  762. top_reg: DestroyReg(PaiObj, TRegister(Op));
  763. top_ref: DestroyRefs(PaiObj, TReference(Op^), R_NO);
  764. top_symbol:;
  765. End;
  766. End;
  767. Function CreateRegs(First: Pai): Pai;
  768. {Starts creating the reg contents for the instructions starting with p.
  769. Returns the last pai which has been processed}
  770. Var
  771. TmpProp: PPaiProp;
  772. Cnt, InstrCnt: Longint;
  773. InstrProp: TAsmInstrucProp;
  774. p: Pai;
  775. TmpRef: TReference;
  776. TmpReg: TRegister;
  777. Begin
  778. p := First;
  779. InstrCnt := 1;
  780. FillChar(NrOfInstrSinceLastMod, SizeOf(NrOfInstrSinceLastMod), 0);
  781. While Assigned(p) Do
  782. Begin
  783. CreateRegs := p;
  784. If (InstrCnt <= NrOfPaiFast)
  785. Then TmpProp := @PaiPropBlock^[InstrCnt]
  786. Else New(TmpProp);
  787. If (p <> First)
  788. Then TmpProp^ := PPaiProp(Pai(p^.previous)^.fileinfo.line)^
  789. Else FillChar(TmpProp^, SizeOf(TmpProp^), 0);
  790. TmpProp^.linesave := p^.fileinfo.line;
  791. PPaiProp(p^.fileinfo.line) := TmpProp;
  792. For TmpReg := R_EAX To R_EDI Do
  793. Inc(NrOfInstrSinceLastMod[TmpReg]);
  794. Case p^.typ Of
  795. ait_label: DestroyAllRegs(p);
  796. ait_labeled_instruction
  797. {$ifdef GDB}
  798. , ait_stabs, ait_stabn,
  799. ait_stab_function_name
  800. {$endif GDB}
  801. :; {nothing changes}
  802. {$ifdef regalloc}
  803. ait_regalloc, ait_regdealloc:;
  804. {$endif regalloc}
  805. ait_instruction:
  806. Begin
  807. InstrProp := AsmInstr[Pai386(p)^._operator];
  808. Case Pai386(p)^._operator Of
  809. {$IfDef OptimizeMovs}
  810. A_MOV, A_MOVZX, A_MOVSX:
  811. Begin
  812. Case Pai386(p)^.op1t Of
  813. Top_Reg:
  814. Case Pai386(p)^.op2t Of
  815. Top_Reg:
  816. Begin
  817. DestroyReg(p, TRegister(Pai386(p)^.op2));
  818. { TmpProp^.Regs[TRegister(Pai386(p)^.op2)] :=
  819. TmpProp^.Regs[TRegister(Pai386(p)^.op1)];
  820. If (TmpProp^.Regs[TRegister(Pai386(p)^.op2)].ModReg = R_NO) Then
  821. TmpProp^.Regs[TRegister(Pai386(p)^.op2)].ModReg :=
  822. Tregister(Pai386(p)^.op1);}
  823. End;
  824. Top_Ref: DestroyRefs(p, TReference(Pai386(p)^.op2^), TRegister(Pai386(p)^.op1));
  825. End;
  826. Top_Ref:
  827. Begin {destination is always a register in this case}
  828. TmpReg := Reg32(TRegister(Pai386(p)^.op2));
  829. If (RegInRef(TmpReg, TReference(Pai386(p)^.op1^)))
  830. Then
  831. Begin
  832. With PPaiProp(Pai(p)^.fileinfo.line)^.Regs[TmpReg] Do
  833. Begin
  834. Inc(State);
  835. {also store how many instructions are part of the sequence in the first
  836. instructions PPaiProp, so it can be easily accessed from within
  837. CheckSequence}
  838. If (typ <> Con_Ref) Then
  839. Begin
  840. typ := Con_Ref;
  841. StartMod := p;
  842. End;
  843. Inc(NrOfMods, NrOfInstrSinceLastMod[TmpReg]);
  844. PPaiProp(Pai(StartMod)^.fileinfo.line)^.Regs[TmpReg].NrOfMods := NrOfMods;
  845. NrOfInstrSinceLastMod[TmpReg] := 0;
  846. End;
  847. End
  848. Else
  849. Begin
  850. DestroyReg(p, TmpReg);
  851. With PPaiProp(Pai(p)^.fileinfo.line)^.Regs[TmpReg] Do
  852. Begin
  853. Typ := Con_Ref;
  854. StartMod := p;
  855. NrOfMods := 1;
  856. End;
  857. End;
  858. End;
  859. Top_Const:
  860. Begin
  861. Case Pai386(p)^.op2t Of
  862. Top_Reg:
  863. Begin
  864. TmpReg := Reg32(TRegister(Pai386(p)^.op2));
  865. With TmpProp^.Regs[TmpReg] Do
  866. Begin
  867. {it doesn't matter that the state is changed,
  868. it isn't looked at when removing constant reloads}
  869. DestroyReg(p, TmpReg);
  870. typ := Con_Const;
  871. StartMod := Pai386(p)^.op1;
  872. End
  873. End;
  874. Top_Ref: DestroyRefs(P, TReference(Pai386(p)^.op2^), R_NO);
  875. End;
  876. End;
  877. End;
  878. End;
  879. {$EndIf OptimizeMovs}
  880. A_IMUL:
  881. Begin
  882. If (Pai386(p)^.Op3t = top_none)
  883. Then
  884. If (Pai386(p)^.Op2t = top_none)
  885. Then
  886. Begin
  887. DestroyReg(p, R_EAX);
  888. DestroyReg(p, R_EDX)
  889. End
  890. Else
  891. Begin
  892. If (Pai386(p)^.Op2t = top_reg) Then
  893. DestroyReg(p, TRegister(Pai386(p)^.Op2));
  894. End
  895. Else If (Pai386(p)^.Op3t = top_reg) Then
  896. DestroyReg(p, TRegister(longint(twowords(Pai386(p)^.Op2).word2)));
  897. End;
  898. A_XOR:
  899. Begin
  900. If (Pai386(p)^.op1t = top_reg) And
  901. (Pai386(p)^.op2t = top_reg) And
  902. (Pai386(p)^.op1 = Pai386(p)^.op2)
  903. Then
  904. Begin
  905. DestroyReg(p, Tregister(Pai386(p)^.op1));
  906. TmpProp^.Regs[Reg32(Tregister(Pai386(p)^.op1))].typ := Con_Const;
  907. TmpProp^.Regs[Reg32(Tregister(Pai386(p)^.op1))].StartMod := Pointer(0)
  908. End
  909. Else Destroy(p, Pai386(p)^.op2t, Pai386(p)^.op2);
  910. End
  911. Else
  912. Begin
  913. If InstrProp.NCh <> 255
  914. Then
  915. For Cnt := 1 To InstrProp.NCh Do
  916. Case InstrProp.Ch[Cnt] Of
  917. C_None:;
  918. C_EAX..C_EDI: DestroyReg(p, TCh2Reg(InstrProp.Ch[Cnt]));
  919. C_CDirFlag: PPaiProp(Pai(p)^.fileinfo.line)^.DirFlag := F_NotSet;
  920. C_SDirFlag: PPaiProp(Pai(p)^.fileinfo.line)^.DirFlag := F_Set;
  921. C_Op1: Destroy(p, Pai386(p)^.op1t, Pai386(p)^.op1);
  922. C_Op2: Destroy(p, Pai386(p)^.op2t, Pai386(p)^.op2);
  923. C_Op3: Destroy(p, Pai386(p)^.op2t, Pointer(Longint(TwoWords(Pai386(p)^.op2).word2)));
  924. C_MemEDI:
  925. Begin
  926. FillChar(TmpRef, SizeOf(TmpRef), 0);
  927. TmpRef.Base := R_EDI;
  928. DestroyRefs(p, TmpRef, R_NO)
  929. End;
  930. C_Flags, C_FPU:;
  931. End
  932. Else
  933. Begin
  934. DestroyAllRegs(p);
  935. End;
  936. End;
  937. End;
  938. End
  939. Else
  940. Begin
  941. DestroyAllRegs(p);
  942. End;
  943. End;
  944. Inc(InstrCnt);
  945. p := Pai(p^.next);
  946. End;
  947. End;
  948. Procedure OptimizeBlock(First, Last: Pai);
  949. {marks the instructions that can be removed by RemoveInstructs. They're not
  950. removed immediately because sometimes an instruction needs to be checked in
  951. two different sequences}
  952. Var Cnt, Cnt2: Longint;
  953. p, hp1, hp2: Pai;
  954. Begin
  955. p := First;
  956. While (p <> Pai(Last^.Next)) Do
  957. Begin
  958. Case p^.typ Of
  959. ait_label, ait_labeled_instruction:;
  960. ait_instruction:
  961. Begin
  962. Case Pai386(p)^._operator Of
  963. A_CLD: If Assigned(p^.previous) And
  964. (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.DirFlag = F_NotSet) Then
  965. PPaiProp(Pai(p)^.fileinfo.line)^.CanBeRemoved := True;
  966. {$IfDef OptimizeMovs}
  967. A_MOV, A_MOVZX, A_MOVSX:
  968. Begin
  969. Case Pai386(p)^.op1t Of
  970. { Top_Reg:
  971. Case Pai386(p)^.op2t Of
  972. Top_Reg:;
  973. Top_Ref:;
  974. End;}
  975. Top_Ref:
  976. Begin {destination is always a register in this case}
  977. With PPaiProp(p^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op2))] Do
  978. Begin
  979. If Assigned(p^.previous) And
  980. (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.
  981. Regs[Reg32(TRegister(Pai386(p)^.op2))].typ = con_ref) Then
  982. {so we don't try to check a sequence when the register only contains a constant}
  983. If CheckSequence(p, TRegister(Pai386(p)^.op2), Cnt) And
  984. (Cnt > 0)
  985. Then
  986. Begin
  987. hp1 := nil;
  988. {although it's perfectly ok to remove an instruction which doesn't contain
  989. the register that we've just checked (CheckSequence takes care of that),
  990. the sequence containing this other register should also be completely
  991. checked and removed, otherwise we may get situations like this:
  992. movl 12(%ebp), %edx movl 12(%ebp), %edx
  993. movl 16(%ebp), %eax movl 16(%ebp), %eax
  994. movl 8(%edx), %edx movl 8(%edx), %edx
  995. movl (%eax), eax movl (%eax), eax
  996. cmpl %eax, %edx cmpl %eax, %edx
  997. jnz l123 getting converted to jnz l123
  998. movl 12(%ebp), %edx movl 4(%eax), eax
  999. movl 16(%ebp), %eax
  1000. movl 8(%edx), %edx
  1001. movl 4(%eax), eax}
  1002. hp2 := p;
  1003. For Cnt2 := 1 to Cnt Do
  1004. Begin
  1005. { Note to Jonas :
  1006. ait_stab_function_name is only at the begin of one function
  1007. ait_stabn is only inserted in ag so you should not see any
  1008. ait_stabs are only in head and tail of procs
  1009. so you should no have problems with those neither !! (PM)
  1010. Tell me if I am wrong
  1011. If Not(Pai(p)^.typ In [ait_stabs, ait_stabn, ait_stab_function_name]) Then }
  1012. Begin
  1013. If (hp1 = nil) And
  1014. Not(RegInInstruction(Tregister(Pai386(hp2)^.op2), p))
  1015. Then hp1 := p;
  1016. PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True;
  1017. End;
  1018. p := Pai(p^.next);
  1019. End;
  1020. If hp1 <> nil Then p := hp1;
  1021. Continue;
  1022. End
  1023. Else
  1024. If (Cnt > 0) And
  1025. (PPaiProp(p^.fileinfo.line)^.CanBeRemoved) Then
  1026. Begin
  1027. hp2 := p;
  1028. For Cnt2 := 1 to Cnt Do
  1029. Begin
  1030. If RegInInstruction(Tregister(Pai386(hp2)^.op2), p)
  1031. Then PPaiProp(p^.fileinfo.line)^.CanBeRemoved := False;
  1032. p := Pai(p^.Next)
  1033. End;
  1034. Continue;
  1035. End;
  1036. End;
  1037. End;
  1038. Top_Const:
  1039. Begin
  1040. Case Pai386(p)^.op2t Of
  1041. Top_Reg:
  1042. Begin
  1043. If Assigned(p^.previous) Then
  1044. With PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg32(TRegister(Pai386(p)^.op2))] Do
  1045. If (Typ = Con_Const) And
  1046. (StartMod = Pai386(p)^.op1) Then
  1047. PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True;
  1048. End;
  1049. Top_Ref:;
  1050. End;
  1051. End;
  1052. End;
  1053. End;
  1054. {$EndIf OptimizeMovs}
  1055. A_STD: If Assigned(p^.previous) And
  1056. (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.DirFlag = F_Set) Then
  1057. PPaiProp(Pai(p)^.fileinfo.line)^.CanBeRemoved := True;
  1058. A_XOR:
  1059. Begin
  1060. If (Pai386(p)^.op1t = top_reg) And
  1061. (Pai386(p)^.op2t = top_reg) And
  1062. (Pai386(p)^.op1 = Pai386(p)^.op2) And
  1063. Assigned(p^.previous) And
  1064. (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].typ = con_const) And
  1065. (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].StartMod = Pointer(0))
  1066. Then PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True
  1067. End
  1068. End
  1069. End;
  1070. End;
  1071. p := Pai(p^.next);
  1072. End;
  1073. End;
  1074. Procedure RemoveInstructs(First, Last: Pai);
  1075. {Removes the marked instructions and disposes the PPaiProps of the other
  1076. instructions, restoring theirline number}
  1077. Var p, hp1: Pai;
  1078. TmpLine, InstrCnt: Longint;
  1079. Begin
  1080. p := First;
  1081. InstrCnt := 1;
  1082. While (p <> Pai(Last^.Next)) Do
  1083. If PPaiProp(p^.fileinfo.line)^.CanBeRemoved
  1084. Then
  1085. Begin
  1086. If (InstrCnt > NrOfPaiFast) Then
  1087. Dispose(PPaiProp(p^.fileinfo.line));
  1088. hp1 := Pai(p^.Next);
  1089. AsmL^.Remove(p);
  1090. Dispose(p, Done);
  1091. p := hp1;
  1092. Inc(InstrCnt)
  1093. End
  1094. Else
  1095. Begin
  1096. If (InstrCnt > NrOfPaiFast)
  1097. Then
  1098. Begin
  1099. TmpLine := PPaiProp(p^.fileinfo.line)^.linesave;
  1100. Dispose(PPaiProp(p^.fileinfo.line));
  1101. p^.fileinfo.line := TmpLine;
  1102. End
  1103. Else p^.fileinfo.line := PPaiProp(p^.fileinfo.line)^.linesave;
  1104. p := Pai(p^.Next);
  1105. Inc(InstrCnt)
  1106. End;
  1107. If (NrOfPaiFast > 0) Then
  1108. {$IfDef TP}
  1109. Freemem(PaiPropBlock, NrOfPaiFast*(((SizeOf(TPaiProp)+1)div 2)*2))
  1110. {$Else}
  1111. FreeMem(PaiPropBlock, NrOfPaiFast*(((SizeOf(TPaiProp)+3)div 4)*4))
  1112. {$EndIf TP}
  1113. End;
  1114. Function InitReloadOpt(AsmL: PAasmOutput): Boolean;
  1115. {reserves memory for the PPaiProps in one big memory block when not using
  1116. TP, returns False if not enough memory is available for the optimizer in all
  1117. cases}
  1118. Var p: Pai;
  1119. Begin
  1120. P := Pai(AsmL^.First);
  1121. NrOfPaiObjs := 1;
  1122. While (P <> Pai(AsmL^.last)) Do
  1123. Begin
  1124. Inc(NrOfPaiObjs);
  1125. P := Pai(P^.next)
  1126. End;
  1127. {$IfDef TP}
  1128. If (MemAvail < (SizeOf(TPaiProp)*NrOfPaiObjs))
  1129. {this doesn't have to be one contiguous block}
  1130. Then InitReloadOpt := False
  1131. Else
  1132. Begin
  1133. InitReloadOpt := True;
  1134. If (MaxAvail < 65520)
  1135. Then NrOfPaiFast := MaxAvail Div (((SizeOf(TPaiProp)+1) div 2)*2)
  1136. Else NrOfPaiFast := 65520 Div (((SizeOf(TPaiProp)+1) div 2)*2);
  1137. If (NrOfPaiFast > 0) Then
  1138. GetMem(PaiPropBlock, NrOfPaiFast*(((SizeOf(TPaiProp)+1) div 2)*2));
  1139. End;
  1140. {$Else}
  1141. {Uncomment the next line to see how much memory the reloading optimizer needs}
  1142. { Writeln((NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4)));}
  1143. {no need to check mem/maxavail, we've got as much virtual memory as we want}
  1144. InitReloadOpt := True;
  1145. GetMem(PaiPropBlock, NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4));
  1146. InitReloadOpt := True;
  1147. NrOfPaiFast := NrOfPaiObjs;
  1148. {$EndIf TP}
  1149. End;
  1150. Var BlockEnd: Pai;
  1151. Begin {ReloadOpt}
  1152. If InitReloadOpt(AsmL)
  1153. Then
  1154. Begin
  1155. BlockEnd := CreateRegs(Pai(AsmL^.First));
  1156. OptimizeBlock(Pai(AsmL^.First), BlockEnd);
  1157. RemoveInstructs(Pai(AsmL^.First), BlockEnd)
  1158. End;
  1159. End;
  1160. {
  1161. $Log$
  1162. Revision 1.7 1998-07-14 14:46:41 peter
  1163. * released NEWINPUT
  1164. Revision 1.6 1998/05/06 08:38:33 pierre
  1165. * better position info with UseTokenInfo
  1166. UseTokenInfo greatly simplified
  1167. + added check for changed tree after first time firstpass
  1168. (if we could remove all the cases were it happen
  1169. we could skip all firstpass if firstpasscount > 1)
  1170. Only with ExtDebug
  1171. Revision 1.5 1998/04/29 10:33:42 pierre
  1172. + added some code for ansistring (not complete nor working yet)
  1173. * corrected operator overloading
  1174. * corrected nasm output
  1175. + started inline procedures
  1176. + added starstarn : use ** for exponentiation (^ gave problems)
  1177. + started UseTokenInfo cond to get accurate positions
  1178. Revision 1.4 1998/04/21 11:30:14 peter
  1179. * fixed $ifdef regalloc
  1180. Revision 1.3 1998/04/16 16:53:56 jonas
  1181. *** empty log message ***
  1182. Revision 1.2 1998/04/06 22:42:32 jonas
  1183. + removal of superflouos cld/std instructions
  1184. Revision 1.1.1.1 1998/03/25 11:18:12 root
  1185. * Restored version
  1186. Revision 1.22 1998/03/24 21:48:29 florian
  1187. * just a couple of fixes applied:
  1188. - problem with fixed16 solved
  1189. - internalerror 10005 problem fixed
  1190. - patch for assembler reading
  1191. - small optimizer fix
  1192. - mem is now supported
  1193. Revision 1.21 1998/03/11 15:45:35 florian
  1194. * -Oa problem solved
  1195. Revision 1.20 1998/03/10 01:17:13 peter
  1196. * all files have the same header
  1197. * messages are fully implemented, EXTDEBUG uses Comment()
  1198. + AG... files for the Assembler generation
  1199. Revision 1.19 1998/03/09 16:46:27 jonas
  1200. * fixed bug with uncertain optimizations when moving data among variables using movsl
  1201. Revision 1.18 1998/03/04 16:42:00 jonas
  1202. * bugfix in destroyrefs and fixed a potential bug in createregs
  1203. Revision 1.17 1998/03/03 20:33:29 jonas
  1204. * TContent record now only occupies 8 bytes anymore
  1205. Revision 1.15 1998/03/03 01:08:13 florian
  1206. * bug0105 and bug0106 problem solved
  1207. Revision 1.14 1998/03/02 21:35:16 jonas
  1208. * added comments from last update
  1209. Revision 1.13 1998/03/02 21:29:06 jonas
  1210. * redesigned TContent record so it occupies only 13 bytes anymore (was about 18)
  1211. * store TPaiProps of 16 and 8 bit registers in those of the 32 bit regs
  1212. * fixed a small bug which prevented some optimizes from being performed
  1213. * store TPaiProps in one big array instead of in seperate records
  1214. * warning: TP version not tested because I only have TP, not BP (-> no proteced mode apps)
  1215. Revision 1.12 1998/02/24 21:18:13 jonas
  1216. * file name back to lower case
  1217. Revision 1.4 1998/02/24 20:32:12 jonas
  1218. * added comments from latest commit
  1219. Revision 1.3 1998/02/24 20:27:51 jonas
  1220. * if a register is being written to memory, it's contents aren't destroyed
  1221. (wherever it's been written to, its contents are up-to-date)
  1222. * changed the order in which some functions/procedure are defined, because some
  1223. of them are now used by aopt386.pas
  1224. Revision 1.11 1998/02/19 22:46:54 peter
  1225. * Fixed linebreaks
  1226. Revision 1.10 1998/02/13 10:34:31 daniel
  1227. * Made Motorola version compilable.
  1228. * Fixed optimizer
  1229. Revision 1.9 1998/02/12 17:18:49 florian
  1230. * fixed to get remake3 work, but needs additional fixes (output, I don't like
  1231. also that aktswitches isn't a pointer)
  1232. Revision 1.8 1998/02/12 11:49:37 daniel
  1233. Yes! Finally! After three retries, my patch!
  1234. Changes:
  1235. Complete rewrite of psub.pas.
  1236. Added support for DLL's.
  1237. Compiler requires less memory.
  1238. Platform units for each platform.
  1239. Revision 1.7 1998/02/07 10:11:19 michael
  1240. * RefsEqual made less harsh:
  1241. * when something is written to x(%ebp), registers which contain
  1242. a pointer that isn't "x(%ebp)"-based isn't destroyed
  1243. * when something is written to a pointer location, registers
  1244. which contain the contents of x(%ebp) aren't destroyed
  1245. Revision 1.6 1998/01/12 17:45:20 jonas
  1246. * merged DisposeProps and RemoveInstructs procedures (speed!)
  1247. Revision 1.5 1998/01/11 22:51:30 jonas
  1248. * back to unix linebreaks...(hate it! :)
  1249. Revision 1.4 1998/01/11 22:50:10 jonas
  1250. * all floating point store operations now change op1 instead of the fpu regs
  1251. Revision 1.3 1998/01/11 14:40:04 jonas
  1252. * bugfix in optimize procedure (too many instructions were removed in certain cases)
  1253. Revision 1.1 1997/12/30 21:10:34 jonas
  1254. * changed back to unix/linux line breaks
  1255. Pre-CVS log:
  1256. JM Jonas Maebe
  1257. + feature added
  1258. - removed
  1259. * bug fixed or changed
  1260. History (started on 2nd December 1997):
  1261. 2nd December 1997:
  1262. + initial version (JM)
  1263. + removes redundant "xor %reg, %reg"'s (JM)
  1264. 3rd December 1997:
  1265. + removes certain redundant movs (still bugged) (JM)
  1266. * A_REP now destroys ECX
  1267. 4th December 1997:
  1268. * fixed bugs in mov-removal (still bugged) (JM)
  1269. 5th December 1997:
  1270. * fixed more bugs in mov-removal (a compiler compiled with these
  1271. optimizations now can compile itself suyccessfully!) and enhanced
  1272. it (introducing new bugs, which have to be fixed again...) (JM)
  1273. * A_AND and A_OR now destroy op2 instead of op1 <g> (JM)
  1274. 6th December 1997:
  1275. * A_PUSHAD now only destroys ESP instead of all registers (JM)
  1276. * A_REPE and A_REPNE now also destroy ECX (JM)
  1277. * Rewrote some procedures so it's a bit more modular and easier/
  1278. cleaner/possible to do some optimizations, but it's slower (JM)
  1279. * enabled mov-reloading optimization for A_MOVZX and A_MOVSX
  1280. (actually it's already 7 December, 1:25 am in the mean time :) (JM)
  1281. 7th December 1997:
  1282. * All instructions okayed by CheckSequence are now being removed (JM)
  1283. To Do:
  1284. * special case for A_XCHG
  1285. * implementation of ModReg comparing
  1286. * special case for lea
  1287. * fpu optimizing
  1288. * active optimizing (ie. change certain register allocations)
  1289. * make DestroyRefs a little less harsh
  1290. * bug fixes?
  1291. }