daopt386.pas 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234
  1. {
  2. $Id$
  3. Copyright (c) 1997-98 by Jonas Maebe
  4. This unit contains the data flow analyzer and several helper procedures
  5. and functions.
  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. {$ifDef TP}
  20. {$UnDef JumpAnal}
  21. {$Endif TP}
  22. Unit DAOpt386;
  23. Interface
  24. Uses
  25. GlobType,
  26. CObjects,Aasm,i386;
  27. Type
  28. TRegArray = Array[R_EAX..R_BL] of TRegister;
  29. TRegSet = Set of R_EAX..R_BL;
  30. TRegInfo = Record
  31. NewRegsEncountered, OldRegsEncountered: TRegSet;
  32. RegsLoadedForRef: TRegSet;
  33. New2OldReg: TRegArray;
  34. End;
  35. {possible actions on an operand: read, write or modify (= read & write)}
  36. TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
  37. {*********************** Procedures and Functions ************************}
  38. Procedure InsertLLItem(AsmL: PAasmOutput; prev, foll, new_one: PLinkedList_Item);
  39. Function Reg32(Reg: TRegister): TRegister;
  40. Function RefsEquivalent(Const R1, R2: TReference; Var RegInfo: TRegInfo; OpAct: TOpAction): Boolean;
  41. Function RefsEqual(Const R1, R2: TReference): Boolean;
  42. Function IsGP32Reg(Reg: TRegister): Boolean;
  43. Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
  44. Function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
  45. Function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
  46. Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
  47. Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
  48. Procedure SkipHead(var P: Pai);
  49. Procedure UpdateUsedRegs(Var UsedRegs: TRegSet; p: Pai);
  50. Function RegsEquivalent(OldReg, NewReg: TRegister; Var RegInfo: TRegInfo; OpAct: TopAction): Boolean;
  51. Function InstructionsEquivalent(p1, p2: Pai; Var RegInfo: TRegInfo): Boolean;
  52. Function OpsEqual(typ: Longint; op1, op2: Pointer): Boolean;
  53. Function DFAPass1(AsmL: PAasmOutput; BlockStart: Pai): Pai;
  54. Function DFAPass2(AsmL: PAasmOutput; BlockStart, BlockEnd: Pai): Boolean;
  55. Procedure ShutDownDFA;
  56. Function FindLabel(L: PLabel; Var hp: Pai): Boolean;
  57. {Procedure FindLoHiLabels(AsmL: PAasmOutput; Var LoLab, HiLab, LabDif: Longint);}
  58. {******************************* Constants *******************************}
  59. Const
  60. {ait_* types which don't result in executable code or which don't influence
  61. the way the program runs/behaves}
  62. SkipInstr = [ait_comment, ait_align, ait_symbol
  63. {$ifdef GDB}
  64. ,ait_stabs, ait_stabn, ait_stab_function_name
  65. {$endif GDB}
  66. ,ait_regalloc, ait_regdealloc
  67. ];
  68. {the maximum number of things (registers, memory, ...) a single instruction
  69. changes}
  70. MaxCh = 3;
  71. {Possible register content types}
  72. con_Unknown = 0;
  73. con_ref = 1;
  74. con_const = 2;
  75. {********************************* Types *********************************}
  76. Type
  77. {What an instruction can change}
  78. TChange = (C_None,
  79. {Read from a register}
  80. C_REAX, C_RECX, C_REDX, C_REBX, C_RESP, C_REBP, C_RESI, C_REDI,
  81. {write from a register}
  82. C_WEAX, C_WECX, C_WEDX, C_WEBX, C_WESP, C_WEBP, C_WESI, C_WEDI,
  83. {read and write from/to a register}
  84. C_RWEAX, C_RWECX, C_RWEDX, C_RWEBX, C_RWESP, C_RWEBP, C_RWESI, C_RWEDI,
  85. C_CDirFlag {clear direction flag}, C_SDirFlag {set dir flag},
  86. C_RFlags, C_WFlags, C_RWFlags, C_FPU,
  87. C_ROp1, C_WOp1, C_RWOp1,
  88. C_ROp2, C_WOp2, C_RWOp2,
  89. C_ROp3, C_WOp3, C_RWOp3,
  90. C_WMemEDI,
  91. C_All);
  92. {the possible states of a flag}
  93. TFlagContents = (F_Unknown, F_NotSet, F_Set);
  94. {the properties of a cpu instruction}
  95. TAsmInstrucProp = Record
  96. {how many things it changes}
  97. { NCh: Byte;}
  98. {and what it changes}
  99. Ch: Array[1..MaxCh] of TChange;
  100. End;
  101. TContent = Record
  102. {start and end of block instructions that defines the
  103. content of this register. If Typ = con_const, then
  104. Longint(StartMod) = value of the constant)}
  105. StartMod: Pointer;
  106. {starts at 0, gets increased everytime the register is written to}
  107. WState: Byte;
  108. {starts at 0, gets increased everytime the register is read from}
  109. RState: Byte;
  110. {how many instructions starting with StarMod does the block consist of}
  111. NrOfMods: Byte;
  112. {the type of the content of the register: unknown, memory, constant}
  113. Typ: Byte;
  114. End;
  115. {Contents of the integer registers}
  116. TRegContent = Array[R_EAX..R_EDI] Of TContent;
  117. {contents of the FPU registers}
  118. TRegFPUContent = Array[R_ST..R_ST7] Of TContent;
  119. {information record with the contents of every register. Every Pai object
  120. gets one of these assigned: a pointer to it is stored in the Line field and
  121. the original line number is stored in LineSave}
  122. TPaiProp = Record
  123. Regs: TRegContent;
  124. { FPURegs: TRegFPUContent;} {currently not yet used}
  125. LineSave: Longint;
  126. {allocated Registers}
  127. UsedRegs: TRegSet;
  128. {status of the direction flag}
  129. DirFlag: TFlagContents;
  130. {can this instruction be removed?}
  131. CanBeRemoved: Boolean;
  132. End;
  133. PPaiProp = ^TPaiProp;
  134. {$IfNDef TP}
  135. TPaiPropBlock = Array[1..250000] Of TPaiProp;
  136. PPaiPropBlock = ^TPaiPropBlock;
  137. {$EndIf TP}
  138. TInstrSinceLastMod = Array[R_EAX..R_EDI] Of Byte;
  139. TLabelTableItem = Record
  140. PaiObj: Pai;
  141. {$IfDef JumpAnal}
  142. InstrNr: Longint;
  143. RefsFound: Word;
  144. JmpsProcessed: Word
  145. {$EndIf JumpAnal}
  146. End;
  147. {$IfDef tp}
  148. TLabelTable = Array[0..10000] Of TLabelTableItem;
  149. {$Else tp}
  150. TLabelTable = Array[0..2500000] Of TLabelTableItem;
  151. {$Endif tp}
  152. PLabelTable = ^TLabelTable;
  153. TwoWords = Record
  154. Word1, Word2: Word;
  155. End;
  156. {******************************* Variables *******************************}
  157. Var
  158. {the amount of PaiObjects in the current assembler list}
  159. NrOfPaiObjs: Longint;
  160. {$IfNDef TP}
  161. {Array which holds all TPaiProps}
  162. PaiPropBlock: PPaiPropBlock;
  163. {$EndIf TP}
  164. LoLab, HiLab, LabDif: Longint;
  165. LTable: PLabelTable;
  166. {*********************** End of Interface section ************************}
  167. Implementation
  168. Uses globals, systems, strings, verbose, hcodegen,
  169. {$ifdef i386}
  170. pass_2;
  171. {$endif i386}
  172. Const AsmInstr: Array[tasmop] Of TAsmInstrucProp = (
  173. {MOV} (Ch: (C_WOp2, C_ROp1, C_None)),
  174. {MOVZX} (Ch: (C_WOp2, C_ROp1, C_None)),
  175. {MOVSX} (Ch: (C_WOp2, C_ROp1, C_None)),
  176. {LABEL} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  177. {ADD} (Ch: (C_RWOp2, C_ROp1, C_WFlags)),
  178. {CALL} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  179. {IDIV} (Ch: (C_RWEAX, C_WEDX, C_WFlags)),
  180. {IMUL} (Ch: (C_RWEAX, C_WEDX, C_WFlags)), {handled separately, because several forms exist}
  181. {JMP} (Ch: (C_None, C_None, C_None)),
  182. {LEA} (Ch: (C_WOp2, C_ROp1, C_None)),
  183. {MUL} (Ch: (C_RWEAX, C_WEDX, C_WFlags)),
  184. {NEG} (Ch: (C_RWOp1, C_None, C_None)),
  185. {NOT} (Ch: (C_RWOp1, C_WFlags, C_None)),
  186. {POP} (Ch: (C_WOp1, C_RWESP, C_None)),
  187. {POPAD} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  188. {PUSH} (Ch: (C_RWESP, C_None, C_None)),
  189. {PUSHAD} (Ch: (C_RWESP, C_None, C_None)),
  190. {RET} (Ch: (C_ALL, C_None, C_None)),
  191. {SUB} (Ch: (C_RWOp2, C_ROp1, C_WFlags)),
  192. {XCHG} (Ch: (C_RWOp1, C_RWOp2, C_None)), {(might be) handled seperately}
  193. {XOR} (Ch: (C_RWOp2, C_ROp1, C_WFlags)),
  194. {FILD} (Ch: (C_FPU, C_None, C_None)),
  195. {CMP} (Ch: (C_WFlags, C_None, C_None)),
  196. {JZ} (Ch: (C_RFlags, C_None, C_None)),
  197. {INC} (Ch: (C_RWOp1, C_WFlags, C_None)),
  198. {DEC} (Ch: (C_RWOp1, C_WFlags, C_None)),
  199. {SETE} (Ch: (C_WOp1, C_RFlags, C_None)),
  200. {SETNE} (Ch: (C_WOp1, C_RFlags, C_None)),
  201. {SETL} (Ch: (C_WOp1, C_RFlags, C_None)),
  202. {SETG} (Ch: (C_WOp1, C_RFlags, C_None)),
  203. {SETLE} (Ch: (C_WOp1, C_RFlags, C_None)),
  204. {SETGE} (Ch: (C_WOp1, C_RFlags, C_None)),
  205. {JE} (Ch: (C_RFlags, C_None, C_None)),
  206. {JNE} (Ch: (C_RFlags, C_None, C_None)),
  207. {JL} (Ch: (C_RFlags, C_None, C_None)),
  208. {JG} (Ch: (C_RFlags, C_None, C_None)),
  209. {JLE} (Ch: (C_RFlags, C_None, C_None)),
  210. {JGE} (Ch: (C_RFlags, C_None, C_None)),
  211. {OR} (Ch: (C_RWOp2, C_WFlags, C_None)),
  212. {FLD} (Ch: (C_ROp1, C_FPU, C_None)),
  213. {FADD} (Ch: (C_FPU, C_None, C_None)),
  214. {FMUL} (Ch: (C_FPU, C_None, C_None)),
  215. {FSUB} (Ch: (C_FPU, C_None, C_None)),
  216. {FDIV} (Ch: (C_FPU, C_None, C_None)),
  217. {FCHS} (Ch: (C_FPU, C_None, C_None)),
  218. {FLD1} (Ch: (C_FPU, C_None, C_None)),
  219. {FIDIV} (Ch: (C_FPU, C_None, C_None)),
  220. {JNZ} (Ch: (C_RFlags, C_None, C_None)),
  221. {FSTP} (Ch: (C_WOp1, C_FPU, C_None)),
  222. {AND} (Ch: (C_RWOp2, C_ROp1, C_WFlags)),
  223. {JNO} (Ch: (C_RFlags, C_None, C_None)),
  224. {NOTH} (Ch: (C_None, C_None, C_None)), {***???***}
  225. {NONE} (Ch: (C_None, C_None, C_None)),
  226. {ENTER} (Ch: (C_RWESP, C_None, C_None)),
  227. {LEAVE} (Ch: (C_RWESP, C_None, C_None)),
  228. {CLD} (Ch: (C_CDirFlag, C_None, C_None)),
  229. {MOVS} (Ch: (C_RWESI, C_RWEDI, C_WMemEDI)),
  230. {REP} (Ch: (C_RWECX, C_RFlags, C_None)),
  231. {SHL} (Ch: (C_RWOp2, C_ROp1, C_WFlags)),
  232. {SHR} (Ch: (C_RWOp2, C_ROp1, C_WFlags)),
  233. {BOUND} (Ch: (C_ROp1, C_None, C_None)),
  234. {JNS} (Ch: (C_RFlags, C_None, C_None)),
  235. {JS} (Ch: (C_RFlags, C_None, C_None)),
  236. {JO} (Ch: (C_RFlags, C_None, C_None)),
  237. {SAR} (Ch: (C_RWOp2, C_ROp1, C_WFlags)),
  238. {TEST} (Ch: (C_WFlags, C_ROp1, C_ROp2)),
  239. {FCOM} (Ch: (C_FPU, C_None, C_None)),
  240. {FCOMP} (Ch: (C_FPU, C_None, C_None)),
  241. {FCOMPP} (Ch: (C_FPU, C_None, C_None)),
  242. {FXCH} (Ch: (C_FPU, C_None, C_None)),
  243. {FADDP} (Ch: (C_FPU, C_None, C_None)),
  244. {FMULP} (Ch: (C_FPU, C_None, C_None)),
  245. {FSUBP} (Ch: (C_FPU, C_None, C_None)),
  246. {FDIVP} (Ch: (C_FPU, C_None, C_None)),
  247. {FNSTS} (Ch: (C_WOp1, C_None, C_None)),
  248. {SAHF} (Ch: (C_WFlags, C_REAX, C_None)),
  249. {FDIVRP} (Ch: (C_FPU, C_None, C_None)),
  250. {FSUBRP} (Ch: (C_FPU, C_None, C_None)),
  251. {SETC} (Ch: (C_WOp1, C_RFlags, C_None)),
  252. {SETNC} (Ch: (C_WOp1, C_RFlags, C_None)),
  253. {JC} (Ch: (C_None, C_RFlags, C_None)),
  254. {JNC} (Ch: (C_RFlags, C_None, C_None)),
  255. {JA} (Ch: (C_RFlags, C_None, C_None)),
  256. {JAE} (Ch: (C_RFlags, C_None, C_None)),
  257. {JB} (Ch: (C_RFlags, C_None, C_None)),
  258. {JBE} (Ch: (C_RFlags, C_None, C_None)),
  259. {SETA} (Ch: (C_WOp1, C_RFlags, C_None)),
  260. {SETAE} (Ch: (C_WOp1, C_RFlags, C_None)),
  261. {SETB} (Ch: (C_WOp1, C_RFlags, C_None)),
  262. {SETBE} (Ch: (C_WOp1, C_RFlags, C_None)),
  263. {AAA} (Ch: (C_RWEAX, C_WFlags, C_None)),
  264. {AAD} (Ch: (C_RWEAX, C_WFlags, C_None)),
  265. {AAM} (Ch: (C_RWEAX, C_WFlags, C_None)),
  266. {AAS} (Ch: (C_RWEAX, C_WFlags, C_None)),
  267. {CBW} (Ch: (C_RWEAX, C_None, C_None)),
  268. {CDQ} (Ch: (C_RWEAX, C_WEDX, C_None)),
  269. {CLC} (Ch: (C_WFlags, C_None, C_None)),
  270. {CLI} (Ch: (C_WFlags, C_None, C_None)),
  271. {CLTS} (Ch: (C_None, C_None, C_None)),
  272. {CMC} (Ch: (C_WFlags, C_None, C_None)),
  273. {CWD} (Ch: (C_RWEAX, C_WEDX, C_None)),
  274. {CWDE} (Ch: (C_RWEAX, C_None, C_None)),
  275. {DAA} (Ch: (C_RWEAX, C_None, C_None)),
  276. {DAS} (Ch: (C_RWEAX, C_None, C_None)),
  277. {HLT} (Ch: (C_None, C_None, C_None)),
  278. {IRET} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  279. {LAHF} (Ch: (C_WEAX, C_RFlags, C_None)),
  280. {LODS} (Ch: (C_WEAX, C_RWESI, C_None)),
  281. {LOCK} (Ch: (C_None, C_None, C_None)),
  282. {NOP} (Ch: (C_None, C_None, C_None)),
  283. {PUSHA} (Ch: (C_ALL, C_None, C_None)), {not true, but a pushall is usually followed by an instruction that does, so
  284. it won hurt either}
  285. {PUSHF} (Ch: (C_RWESP, C_RFlags, C_None)),
  286. {PUSHFD} (Ch: (C_RWESP, C_RFlags, C_None)),
  287. {STC} (Ch: (C_WFlags, C_None, C_None)),
  288. {STD} (Ch: (C_SDirFlag, C_None, C_None)),
  289. {STI} (Ch: (C_WFlags, C_None, C_None)),
  290. {STOS} (Ch: (C_WMemEDI, C_RWEDI, C_REAX)),
  291. {WAIT} (Ch: (C_None, C_None, C_None)),
  292. {XLAT} (Ch: (C_WEAX, C_REBX, C_None)),
  293. {XLATB} (Ch: (C_WEAX, C_REBX, C_None)),
  294. {MOVSB} (Ch: (C_WOp2, C_ROp1, C_None)),
  295. {MOVSBL} (Ch: (C_WOp2, C_ROp1, C_None)),
  296. {MOVSBW} (Ch: (C_WOp2, C_ROp1, C_None)),
  297. {MOVSWL} (Ch: (C_WOp2, C_ROp1, C_None)),
  298. {MOVZB} (Ch: (C_WOp2, C_ROp1, C_None)),
  299. {MOVZWL} (Ch: (C_WOp2, C_ROp1, C_None)),
  300. {POPA} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  301. {IN} (Ch: (C_WOp2, C_ROp1, C_None)),
  302. {OUT} (Ch: (C_ROp1, C_ROp2, C_None)),
  303. {LDS} (Ch: (C_WOp2, C_None, C_None)),
  304. {LCS} (Ch: (C_WOp2, C_None, C_None)),
  305. {LES} (Ch: (C_WOp2, C_None, C_None)),
  306. {LFS} (Ch: (C_WOp2, C_None, C_None)),
  307. {LGS} (Ch: (C_WOp2, C_None, C_None)),
  308. {LSS} (Ch: (C_WOp2, C_None, C_None)),
  309. {POPF} (Ch: (C_RWESP, C_WFlags, C_None)),
  310. {SBB} (Ch: (C_RWOp2, C_ROp1, C_RWFlags)),
  311. {ADC} (Ch: (C_RWOp2, C_ROp1, C_RWFlags)),
  312. {DIV} (Ch: (C_RWEAX, C_WEDX, C_WFlags)),
  313. {ROR} (Ch: (C_RWOp2, C_ROp1, C_RWFlags)),
  314. {ROL} (Ch: (C_RWOp2, C_ROp1, C_RWFlags)),
  315. {RCL} (Ch: (C_RWOp2, C_ROp1, C_RWFlags)),
  316. {RCR} (Ch: (C_RWOp2, C_ROp1, C_RWFlags)),
  317. {SAL} (Ch: (C_RWOp2, C_ROp1, C_RWFlags)),
  318. {SHLD} (Ch: (C_RWOp3, C_RWFlags, C_ROp2)),
  319. {SHRD} (Ch: (C_RWOp3, C_RWFlags, C_ROp2)),
  320. {LCALL} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  321. {LJMP} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  322. {LRET} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  323. {JNAE} (Ch: (C_RFlags, C_None, C_None)),
  324. {JNB} (Ch: (C_RFlags, C_None, C_None)),
  325. {JNA} (Ch: (C_RFlags, C_None, C_None)),
  326. {JNBE} (Ch: (C_RFlags, C_None, C_None)),
  327. {JP} (Ch: (C_RFlags, C_None, C_None)),
  328. {JNP} (Ch: (C_RFlags, C_None, C_None)),
  329. {JPE} (Ch: (C_RFlags, C_None, C_None)),
  330. {JPO} (Ch: (C_RFlags, C_None, C_None)),
  331. {JNGE} (Ch: (C_RFlags, C_None, C_None)),
  332. {JNG} (Ch: (C_RFlags, C_None, C_None)),
  333. {JNL} (Ch: (C_RFlags, C_None, C_None)),
  334. {JNLE} (Ch: (C_RFlags, C_None, C_None)),
  335. {JCXZ} (Ch: (C_RECX, C_None, C_None)),
  336. {JECXZ} (Ch: (C_RECX, C_None, C_None)),
  337. {LOOP} (Ch: (C_RWECX, C_None, C_None)),
  338. {CMPS} (Ch: (C_RWESI, C_RWEDI, C_WFlags)),
  339. {INS} (Ch: (C_RWEDI, C_WMemEDI, C_None)),
  340. {OUTS} (Ch: (C_RWESI, C_None, C_None)),
  341. {SCAS} (Ch: (C_RWEDI, C_WFlags, C_None)),
  342. {BSF} (Ch: (C_WOp2, C_WFlags, C_ROp1)),
  343. {BSR} (Ch: (C_WOp2, C_WFlags, C_ROp1)),
  344. {BT} (Ch: (C_WFlags, C_ROp1, C_None)),
  345. {BTC} (Ch: (C_RWOp2, C_ROp1, C_WFlags)),
  346. {BTR} (Ch: (C_RWOp2, C_ROp1, C_WFlags)),
  347. {BTS} (Ch: (C_RWOp2, C_ROp1, C_WFlags)),
  348. {INT} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  349. {INT3} (Ch: (C_None, C_None, C_None)),
  350. {INTO} (Ch: (C_All, C_None, C_None)), {don't know value of any register}
  351. {BOUNDL} (Ch: (C_ROp1, C_None, C_None)),
  352. {BOUNDW} (Ch: (C_ROp1, C_None, C_None)),
  353. {LOOPZ} (Ch: (C_RWECX, C_RFlags, C_None)),
  354. {LOOPE} (Ch: (C_RWECX, C_RFlags, C_None)),
  355. {LOOPNZ} (Ch: (C_RWECX, C_RFlags, C_None)),
  356. {LOOPNE} (Ch: (C_RWECX, C_RFlags, C_None)),
  357. {SETO} (Ch: (C_WOp1, C_RFlags, C_None)),
  358. {SETNO} (Ch: (C_WOp1, C_RFlags, C_None)),
  359. {SETNAE} (Ch: (C_WOp1, C_RFlags, C_None)),
  360. {SETNB} (Ch: (C_WOp1, C_RFlags, C_None)),
  361. {SETZ} (Ch: (C_WOp1, C_RFlags, C_None)),
  362. {SETNZ} (Ch: (C_WOp1, C_RFlags, C_None)),
  363. {SETNA} (Ch: (C_WOp1, C_RFlags, C_None)),
  364. {SETNBE} (Ch: (C_WOp1, C_RFlags, C_None)),
  365. {SETS} (Ch: (C_WOp1, C_RFlags, C_None)),
  366. {SETNS} (Ch: (C_WOp1, C_RFlags, C_None)),
  367. {SETP} (Ch: (C_WOp1, C_RFlags, C_None)),
  368. {SETPE} (Ch: (C_WOp1, C_RFlags, C_None)),
  369. {SETNP} (Ch: (C_WOp1, C_RFlags, C_None)),
  370. {SETPO} (Ch: (C_WOp1, C_RFlags, C_None)),
  371. {SETNGE} (Ch: (C_WOp1, C_RFlags, C_None)),
  372. {SETNL} (Ch: (C_WOp1, C_RFlags, C_None)),
  373. {SETNG} (Ch: (C_WOp1, C_RFlags, C_None)),
  374. {SETNLE} (Ch: (C_WOp1, C_RFlags, C_None)),
  375. {ARPL} (Ch: (C_WFlags, C_None, C_None)),
  376. {LAR} (Ch: (C_WOp2, C_None, C_None)),
  377. {LGDT} (Ch: (C_None, C_None, C_None)),
  378. {LIDT} (Ch: (C_None, C_None, C_None)),
  379. {LLDT} (Ch: (C_None, C_None, C_None)),
  380. {LMSW} (Ch: (C_None, C_None, C_None)),
  381. {LSL} (Ch: (C_WOp2, C_WFlags, C_None)),
  382. {LTR} (Ch: (C_None, C_None, C_None)),
  383. {SGDT} (Ch: (C_WOp1, C_None, C_None)),
  384. {SIDT} (Ch: (C_WOp1, C_None, C_None)),
  385. {SLDT} (Ch: (C_WOp1, C_None, C_None)),
  386. {SMSW} (Ch: (C_WOp1, C_None, C_None)),
  387. {STR} (Ch: (C_WOp1, C_None, C_None)),
  388. {VERR} (Ch: (C_WFlags, C_None, C_None)),
  389. {VERW} (Ch: (C_WFlags, C_None, C_None)),
  390. {FABS} (Ch: (C_FPU, C_None, C_None)),
  391. {FBLD} (Ch: (C_ROp1, C_FPU, C_None)),
  392. {FBSTP} (Ch: (C_WOp1, C_FPU, C_None)),
  393. {FCLEX} (Ch: (C_FPU, C_None, C_None)),
  394. {FNCLEX} (Ch: (C_FPU, C_None, C_None)),
  395. {FCOS} (Ch: (C_FPU, C_None, C_None)),
  396. {FDECSTP}(Ch: (C_FPU, C_None, C_None)),
  397. {FDISI} (Ch: (C_FPU, C_None, C_None)),
  398. {FNDISI} (Ch: (C_FPU, C_None, C_None)),
  399. {FDIVR} (Ch: (C_FPU, C_None, C_None)),
  400. {FENI} (Ch: (C_FPU, C_None, C_None)),
  401. {FNENI} (Ch: (C_FPU, C_None, C_None)),
  402. {FFREE} (Ch: (C_FPU, C_None, C_None)),
  403. {FIADD} (Ch: (C_FPU, C_None, C_None)),
  404. {FICOM} (Ch: (C_FPU, C_None, C_None)),
  405. {FICOMP} (Ch: (C_FPU, C_None, C_None)),
  406. {FIDIVR} (Ch: (C_FPU, C_None, C_None)),
  407. {FIMUL} (Ch: (C_FPU, C_None, C_None)),
  408. {FINCSTP}(Ch: (C_FPU, C_None, C_None)),
  409. {FINIT} (Ch: (C_FPU, C_None, C_None)),
  410. {FNINIT} (Ch: (C_FPU, C_None, C_None)),
  411. {FIST} (Ch: (C_WOp1, C_None, C_None)),
  412. {FISTP} (Ch: (C_WOp1, C_None, C_None)),
  413. {FISUB} (Ch: (C_FPU, C_None, C_None)),
  414. {FSUBR} (Ch: (C_FPU, C_None, C_None)),
  415. {FLDCW} (Ch: (C_FPU, C_None, C_None)),
  416. {FLDENV} (Ch: (C_FPU, C_None, C_None)),
  417. {FLDLG2} (Ch: (C_FPU, C_None, C_None)),
  418. {FLDLN2} (Ch: (C_FPU, C_None, C_None)),
  419. {FLDL2E} (Ch: (C_FPU, C_None, C_None)),
  420. {FLDL2T} (Ch: (C_FPU, C_None, C_None)),
  421. {FLDPI} (Ch: (C_FPU, C_None, C_None)),
  422. {FLDS} (Ch: (C_FPU, C_None, C_None)),
  423. {FLDZ} (Ch: (C_FPU, C_None, C_None)),
  424. {FNOP} (Ch: (C_FPU, C_None, C_None)),
  425. {FPATAN} (Ch: (C_FPU, C_None, C_None)),
  426. {FPREM} (Ch: (C_FPU, C_None, C_None)),
  427. {FPREM1} (Ch: (C_FPU, C_None, C_None)),
  428. {FPTAN} (Ch: (C_FPU, C_None, C_None)),
  429. {FRNDINT}(Ch: (C_FPU, C_None, C_None)),
  430. {FRSTOR} (Ch: (C_FPU, C_None, C_None)),
  431. {FSAVE} (Ch: (C_WOp1, C_None, C_None)),
  432. {FNSAVE} (Ch: (C_FPU, C_None, C_None)),
  433. {FSCALE} (Ch: (C_FPU, C_None, C_None)),
  434. {FSETPM} (Ch: (C_FPU, C_None, C_None)),
  435. {FSIN} (Ch: (C_FPU, C_None, C_None)),
  436. {FSINCOS}(Ch: (C_FPU, C_None, C_None)),
  437. {FSQRT} (Ch: (C_FPU, C_None, C_None)),
  438. {FST} (Ch: (C_WOp1, C_None, C_None)),
  439. {FSTCW} (Ch: (C_WOp1, C_None, C_None)),
  440. {FNSTCW} (Ch: (C_WOp1, C_None, C_None)),
  441. {FSTENV} (Ch: (C_WOp1, C_None, C_None)),
  442. {FNSTENV}(Ch: (C_WOp1, C_None, C_None)),
  443. {FSTSW} (Ch: (C_WOp1, C_None, C_None)),
  444. {FNSTSW} (Ch: (C_WOp1, C_None, C_None)),
  445. {FTST} (Ch: (C_FPU, C_None, C_None)),
  446. {FUCOM} (Ch: (C_FPU, C_None, C_None)),
  447. {FUCOMP} (Ch: (C_FPU, C_None, C_None)),
  448. {FUCOMPP}(Ch: (C_FPU, C_None, C_None)),
  449. {FWAIT} (Ch: (C_FPU, C_None, C_None)),
  450. {FXAM} (Ch: (C_FPU, C_None, C_None)),
  451. {FXTRACT}(Ch: (C_FPU, C_None, C_None)),
  452. {FYL2X} (Ch: (C_FPU, C_None, C_None)),
  453. {FYL2XP1}(Ch: (C_FPU, C_None, C_None)),
  454. {F2XM1} (Ch: (C_FPU, C_None, C_None)),
  455. {FILDQ} (Ch: (C_FPU, C_None, C_None)),
  456. {FILDS} (Ch: (C_FPU, C_None, C_None)),
  457. {FILDL} (Ch: (C_FPU, C_None, C_None)),
  458. {FLDL} (Ch: (C_FPU, C_None, C_None)),
  459. {FLDT} (Ch: (C_FPU, C_None, C_None)),
  460. {FISTQ} (Ch: (C_WOp1, C_None, C_None)),
  461. {FISTS} (Ch: (C_WOp1, C_None, C_None)),
  462. {FISTL} (Ch: (C_WOp1, C_None, C_None)),
  463. {FSTL} (Ch: (C_WOp1, C_None, C_None)),
  464. {FSTS} (Ch: (C_WOp1, C_None, C_None)),
  465. {FSTPS} (Ch: (C_WOp1, C_FPU, C_None)),
  466. {FISTPL} (Ch: (C_WOp1, C_None, C_None)),
  467. {FSTPL} (Ch: (C_WOp1, C_FPU, C_None)),
  468. {FISTPS} (Ch: (C_WOp1, C_FPU, C_None)),
  469. {FISTPQ} (Ch: (C_WOp1, C_FPU, C_None)),
  470. {FSTPT} (Ch: (C_WOp1, C_FPU, C_None)),
  471. {FCOMPS} (Ch: (C_FPU, C_None, C_None)),
  472. {FICOMPL}(Ch: (C_FPU, C_None, C_None)),
  473. {FCOMPL} (Ch: (C_FPU, C_None, C_None)),
  474. {FICOMPS}(Ch: (C_FPU, C_None, C_None)),
  475. {FCOMS} (Ch: (C_FPU, C_None, C_None)),
  476. {FICOML} (Ch: (C_FPU, C_None, C_None)),
  477. {FCOML} (Ch: (C_FPU, C_None, C_None)),
  478. {FICOMS} (Ch: (C_FPU, C_None, C_None)),
  479. {FIADDL} (Ch: (C_FPU, C_None, C_None)),
  480. {FADDL} (Ch: (C_FPU, C_None, C_None)),
  481. {FIADDS} (Ch: (C_FPU, C_None, C_None)),
  482. {FISUBL} (Ch: (C_FPU, C_None, C_None)),
  483. {FSUBL} (Ch: (C_FPU, C_None, C_None)),
  484. {FISUBS} (Ch: (C_FPU, C_None, C_None)),
  485. {FSUBS} (Ch: (C_FPU, C_None, C_None)),
  486. {FSUBR} (Ch: (C_FPU, C_None, C_None)),
  487. {FSUBRS} (Ch: (C_FPU, C_None, C_None)),
  488. {FISUBRL}(Ch: (C_FPU, C_None, C_None)),
  489. {FSUBRL} (Ch: (C_FPU, C_None, C_None)),
  490. {FISUBRS}(Ch: (C_FPU, C_None, C_None)),
  491. {FMULS} (Ch: (C_FPU, C_None, C_None)),
  492. {FIMUL} (Ch: (C_FPU, C_None, C_None)),
  493. {FMULL} (Ch: (C_FPU, C_None, C_None)),
  494. {FIMULS} (Ch: (C_FPU, C_None, C_None)),
  495. {FIDIVS} (Ch: (C_FPU, C_None, C_None)),
  496. {FIDIVL} (Ch: (C_FPU, C_None, C_None)),
  497. {FDIVL} (Ch: (C_FPU, C_None, C_None)),
  498. {FIDIVS} (Ch: (C_FPU, C_None, C_None)),
  499. {FDIVRS} (Ch: (C_FPU, C_None, C_None)),
  500. {FIDIVRL}(Ch: (C_FPU, C_None, C_None)),
  501. {FDIVRL} (Ch: (C_FPU, C_None, C_None)),
  502. {FIDIVRS}(Ch: (C_FPU, C_None, C_None)),
  503. {REPE} (Ch: (C_RWECX, C_RFlags, C_None)),
  504. {REPNE} (Ch: (C_RWECX, C_RFlags, C_None)),
  505. {CPUID} (Ch: (C_All, C_None, C_none)),
  506. {FADDS} (Ch: (C_FPU, C_None, C_None)),
  507. {POPFD} (Ch: (C_RWESP, C_WFlags, C_None)),
  508. {below are the MMX instructions}
  509. {A_EMMS} (Ch: (C_FPU, C_None, C_None)),
  510. {A_MOVD} (Ch: (C_WOp2, C_None, C_None)),
  511. {A_MOVQ} (Ch: (C_WOp2, C_None, C_None)),
  512. {A_PACKSSDW} (Ch: (C_All, C_None, C_None)),
  513. {A_PACKSSWB} (Ch: (C_All, C_None, C_None)),
  514. {A_PACKUSWB} (Ch: (C_All, C_None, C_None)),
  515. {A_PADDB} (Ch: (C_RWOp2, C_None, C_None)),
  516. {A_PADDD} (Ch: (C_RWOp2, C_None, C_None)),
  517. {A_PADDSB} (Ch: (C_RWOp2, C_None, C_None)),
  518. {A_PADDSW} (Ch: (C_RWOp2, C_None, C_None)),
  519. {A_PADDUSB} (Ch: (C_RWOp2, C_None, C_None)),
  520. {A_PADDUSW} (Ch: (C_RWOp2, C_None, C_None)),
  521. {A_PADDW} (Ch: (C_RWOp2, C_None, C_None)),
  522. {A_PAND} (Ch: (C_RWOp2, C_None, C_None)),
  523. {A_PANDN} (Ch: (C_RWOp2, C_None, C_None)),
  524. {A_PCMPEQB} (Ch: (C_All, C_None, C_None)),
  525. {A_PCMPEQD} (Ch: (C_All, C_None, C_None)),
  526. {A_PCMPEQW} (Ch: (C_All, C_None, C_None)),
  527. {A_PCMPGTB} (Ch: (C_All, C_None, C_None)),
  528. {A_PCMPGTD} (Ch: (C_All, C_None, C_None)),
  529. {A_PCMPGTW} (Ch: (C_All, C_None, C_None)),
  530. {A_PMADDWD} (Ch: (C_RWOp2, C_None, C_None)),
  531. {A_PMULHW} (Ch: (C_All, C_None, C_None)),
  532. {A_PMULLW} (Ch: (C_All, C_None, C_None)),
  533. {A_POR} (Ch: (C_RWOp2, C_None, C_None)),
  534. {A_PSLLD} (Ch: (C_RWOp2, C_None, C_None)),
  535. {A_PSLLQ} (Ch: (C_RWOp2, C_None, C_None)),
  536. {A_PSLLW} (Ch: (C_RWOp2, C_None, C_None)),
  537. {A_PSRAD} (Ch: (C_RWOp2, C_None, C_None)),
  538. {A_PSRAW} (Ch: (C_RWOp2, C_None, C_None)),
  539. {A_PSRLD} (Ch: (C_RWOp2, C_None, C_None)),
  540. {A_PSRLQ} (Ch: (C_RWOp2, C_None, C_None)),
  541. {A_PSRLW} (Ch: (C_RWOp2, C_None, C_None)),
  542. {A_PSUBB} (Ch: (C_RWOp2, C_None, C_None)),
  543. {A_PSUBD} (Ch: (C_RWOp2, C_None, C_None)),
  544. {A_PSUBSB} (Ch: (C_RWOp2, C_None, C_None)),
  545. {A_PSUBSW} (Ch: (C_RWOp2, C_None, C_None)),
  546. {A_PSUBUSB} (Ch: (C_RWOp2, C_None, C_None)),
  547. {A_PSUBUSW} (Ch: (C_RWOp2, C_None, C_None)),
  548. {A_PSUBW} (Ch: (C_RWOp2, C_None, C_None)),
  549. {A_PUNPCKHBW} (Ch: (C_All, C_None, C_None)),
  550. {A_PUNPCKHDQ} (Ch: (C_All, C_None, C_None)),
  551. {A_PUNPCKHWD} (Ch: (C_All, C_None, C_None)),
  552. {A_PUNPCKLBW} (Ch: (C_All, C_None, C_None)),
  553. {A_PUNPCKLDQ} (Ch: (C_All, C_None, C_None)),
  554. {A_PUNPCKLWD} (Ch: (C_All, C_None, C_None)),
  555. {A_PXOR} (Ch: (C_RWOp2, C_None, C_None)));
  556. Var
  557. {How many instructions are between the current instruction and the last one
  558. that modified the register}
  559. NrOfInstrSinceLastMod: TInstrSinceLastMod;
  560. {************************ Create the Label table ************************}
  561. Function FindLoHiLabels(AsmL: PAasmOutput; Var LowLabel, HighLabel, LabelDif: Longint; BlockStart: Pai): Pai;
  562. {Walks through the paasmlist to find the lowest and highest label number;
  563. Since 0.9.3: also removes unused labels}
  564. Var LabelFound: Boolean;
  565. P: Pai;
  566. Begin
  567. LabelFound := False;
  568. LowLabel := MaxLongint;
  569. HighLabel := 0;
  570. P := BlockStart;
  571. While Assigned(P) And
  572. ((P^.typ <> Ait_Marker) Or
  573. (Pai_Marker(P)^.Kind <> AsmBlockStart)) Do
  574. Begin
  575. If (Pai(p)^.typ = ait_label) Then
  576. If (Pai_Label(p)^.l^.is_used)
  577. Then
  578. Begin
  579. LabelFound := True;
  580. If (Pai_Label(p)^.l^.nb < LowLabel) Then
  581. LowLabel := Pai_Label(p)^.l^.nb;
  582. If (Pai_Label(p)^.l^.nb > HighLabel) Then
  583. HighLabel := Pai_Label(p)^.l^.nb;
  584. End
  585. { Else
  586. Begin
  587. hp1 := pai(p^.next);
  588. AsmL^.Remove(p);
  589. Dispose(p, Done);
  590. p := hp1;
  591. continue;
  592. End};
  593. GetNextInstruction(p, p);
  594. End;
  595. FindLoHiLabels := p;
  596. If LabelFound
  597. Then LabelDif := HighLabel+1-LowLabel
  598. Else LabelDif := 0;
  599. End;
  600. Function FindRegAlloc(Reg: TRegister; StartPai: Pai): Boolean;
  601. {Returns true if a ait_regalloc object for Reg is found in the block of Pai's
  602. starting with StartPai and ending with the next "real" instruction}
  603. Var TmpResult: Boolean;
  604. Begin
  605. TmpResult := False;
  606. Repeat
  607. While Assigned(StartPai) And
  608. ((StartPai^.typ in (SkipInstr - [ait_RegAlloc])) Or
  609. ((StartPai^.typ = ait_label) and
  610. Not(Pai_Label(StartPai)^.l^.Is_Used))) Do
  611. StartPai := Pai(StartPai^.Next);
  612. If Assigned(StartPai) And
  613. (StartPai^.typ = ait_RegAlloc) Then
  614. Begin
  615. TmpResult := (PaiRegAlloc(StartPai)^.Reg = Reg);
  616. StartPai := Pai(StartPai^.Next);
  617. End;
  618. Until Not(Assigned(StartPai)) Or
  619. Not(StartPai^.typ in SkipInstr) or TmpResult;
  620. FindRegAlloc := TmpResult;
  621. End;
  622. Procedure BuildLabelTableAndFixRegAlloc(AsmL: PAasmOutput; Var LabelTable: PLabelTable; LowLabel: Longint;
  623. Var LabelDif: Longint; BlockStart, BlockEnd: Pai);
  624. {Builds a table with the locations of the labels in the paasmoutput.
  625. Also fixes some RegDeallocs like "# %eax released; push (%eax)"}
  626. Var p, hp1, hp2: Pai;
  627. UsedRegs: TRegSet;
  628. Begin
  629. UsedRegs := [];
  630. If (LabelDif <> 0) Then
  631. Begin
  632. {$IfDef TP}
  633. If (MaxAvail >= LabelDif*SizeOf(Pai))
  634. Then
  635. Begin
  636. {$EndIf TP}
  637. GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
  638. FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
  639. p := BlockStart;
  640. While (P <> BlockEnd) Do
  641. Begin
  642. Case p^.typ Of
  643. ait_Label:
  644. If Pai_Label(p)^.l^.is_used Then
  645. LabelTable^[Pai_Label(p)^.l^.nb-LowLabel].PaiObj := p;
  646. ait_RegAlloc:
  647. Begin
  648. If Not(PaiRegAlloc(p)^.Reg in UsedRegs) Then
  649. UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg]
  650. Else
  651. Begin
  652. hp1 := p;
  653. hp2 := nil;
  654. While GetLastInstruction(hp1, hp1) And
  655. Not(RegInInstruction(PaiRegAlloc(p)^.Reg, hp1)) Do
  656. hp2 := hp1;
  657. If hp2 <> nil Then
  658. Begin
  659. hp1 := New(PaiRegDeAlloc, Init(PaiRegAlloc(p)^.Reg));
  660. InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp1);
  661. End;
  662. End;
  663. End;
  664. ait_RegDeAlloc:
  665. Begin
  666. UsedRegs := UsedRegs - [PaiRegDeAlloc(p)^.Reg];
  667. hp1 := p;
  668. hp2 := nil;
  669. While Not(FindRegAlloc(PaiRegDeAlloc(p)^.Reg, Pai(hp1^.Next))) And
  670. GetNextInstruction(hp1, hp1) And
  671. RegInInstruction(PaiRegDeAlloc(p)^.Reg, hp1) Do
  672. hp2 := hp1;
  673. If hp2 <> nil Then
  674. Begin
  675. hp1 := Pai(p^.previous);
  676. AsmL^.Remove(p);
  677. InsertLLItem(AsmL, hp2, Pai(hp2^.Next), p);
  678. p := hp1;
  679. End;
  680. End;
  681. End;
  682. P := Pai(p^.Next);
  683. While Assigned(p) And
  684. (p^.typ in (SkipInstr - [ait_regdealloc,ait_regalloc])) Do
  685. P := Pai(P^.Next);
  686. End;
  687. {$IfDef TP}
  688. End
  689. Else LabelDif := 0;
  690. {$EndIf TP}
  691. End;
  692. End;
  693. {************************ Search the Label table ************************}
  694. Function FindLabel(L: PLabel; Var hp: Pai): Boolean;
  695. {searches for the specified label starting from hp as long as the
  696. encountered instructions are labels, to be able to optimize constructs like
  697. jne l2 jmp l2
  698. jmp l3 and l1:
  699. l1: l2:
  700. l2:}
  701. Var TempP: Pai;
  702. Begin
  703. TempP := hp;
  704. While Assigned(TempP) and
  705. (TempP^.typ In SkipInstr + [ait_label]) Do
  706. If (TempP^.typ <> ait_Label) Or
  707. (pai_label(TempP)^.l <> L)
  708. Then GetNextInstruction(TempP, TempP)
  709. Else
  710. Begin
  711. hp := TempP;
  712. FindLabel := True;
  713. exit
  714. End;
  715. FindLabel := False;
  716. End;
  717. {************************ Some general functions ************************}
  718. Function Reg32(Reg: TRegister): TRegister;
  719. {Returns the 32 bit component of Reg if it exists, otherwise Reg is returned}
  720. Begin
  721. Reg32 := Reg;
  722. If (Reg >= R_AX)
  723. Then
  724. If (Reg <= R_DI)
  725. Then Reg32 := Reg16ToReg32(Reg)
  726. Else
  727. If (Reg <= R_BL)
  728. Then Reg32 := Reg8toReg32(Reg);
  729. End;
  730. { inserts new_one between prev and foll }
  731. Procedure InsertLLItem(AsmL: PAasmOutput; prev, foll, new_one: PLinkedList_Item);
  732. Begin
  733. If Assigned(prev) Then
  734. If Assigned(foll) Then
  735. Begin
  736. If Assigned(new_one) Then
  737. Begin
  738. new_one^.previous := prev;
  739. new_one^.next := foll;
  740. prev^.next := new_one;
  741. foll^.previous := new_one;
  742. End;
  743. End
  744. Else AsmL^.Concat(new_one)
  745. Else If Assigned(Foll) Then AsmL^.Insert(new_one)
  746. End;
  747. {********************* Compare parts of Pai objects *********************}
  748. Function RegsSameSize(Reg1, Reg2: TRegister): Boolean;
  749. {returns true if Reg1 and Reg2 are of the same size (so if they're both
  750. 8bit, 16bit or 32bit)}
  751. Begin
  752. If (Reg1 <= R_EDI)
  753. Then RegsSameSize := (Reg2 <= R_EDI)
  754. Else
  755. If (Reg1 <= R_DI)
  756. Then RegsSameSize := (Reg2 in [R_AX..R_DI])
  757. Else
  758. If (Reg1 <= R_BL)
  759. Then RegsSameSize := (Reg2 in [R_AL..R_BL])
  760. Else RegsSameSize := False
  761. End;
  762. Procedure AddReg2RegInfo(OldReg, NewReg: TRegister; Var RegInfo: TRegInfo);
  763. {updates the ???RegsEncountered and ???2???Reg fields of RegInfo. Assumes that
  764. OldReg and NewReg have the same size (has to be chcked in advance with
  765. RegsSameSize) and that neither equals R_NO}
  766. Begin
  767. With RegInfo Do
  768. Begin
  769. NewRegsEncountered := NewRegsEncountered + [NewReg];
  770. OldRegsEncountered := OldRegsEncountered + [OldReg];
  771. New2OldReg[NewReg] := OldReg;
  772. Case OldReg Of
  773. R_EAX..R_EDI:
  774. Begin
  775. NewRegsEncountered := NewRegsEncountered + [Reg32toReg16(NewReg)];
  776. OldRegsEncountered := OldRegsEncountered + [Reg32toReg16(OldReg)];
  777. New2OldReg[Reg32toReg16(NewReg)] := Reg32toReg16(OldReg);
  778. If (NewReg in [R_EAX..R_EBX]) And
  779. (OldReg in [R_EAX..R_EBX]) Then
  780. Begin
  781. NewRegsEncountered := NewRegsEncountered + [Reg32toReg8(NewReg)];
  782. OldRegsEncountered := OldRegsEncountered + [Reg32toReg8(OldReg)];
  783. New2OldReg[Reg32toReg8(NewReg)] := Reg32toReg8(OldReg);
  784. End;
  785. End;
  786. R_AX..R_DI:
  787. Begin
  788. NewRegsEncountered := NewRegsEncountered + [Reg16toReg32(NewReg)];
  789. OldRegsEncountered := OldRegsEncountered + [Reg16toReg32(OldReg)];
  790. New2OldReg[Reg16toReg32(NewReg)] := Reg16toReg32(OldReg);
  791. If (NewReg in [R_AX..R_BX]) And
  792. (OldReg in [R_AX..R_BX]) Then
  793. Begin
  794. NewRegsEncountered := NewRegsEncountered + [Reg16toReg8(NewReg)];
  795. OldRegsEncountered := OldRegsEncountered + [Reg16toReg8(OldReg)];
  796. New2OldReg[Reg16toReg8(NewReg)] := Reg16toReg8(OldReg);
  797. End;
  798. End;
  799. R_AL..R_BL:
  800. Begin
  801. NewRegsEncountered := NewRegsEncountered + [Reg8toReg32(NewReg)]
  802. + [Reg8toReg16(NewReg)];
  803. OldRegsEncountered := OldRegsEncountered + [Reg8toReg32(OldReg)]
  804. + [Reg8toReg16(OldReg)];
  805. New2OldReg[Reg8toReg32(NewReg)] := Reg8toReg32(OldReg);
  806. End;
  807. End;
  808. End;
  809. End;
  810. Procedure AddOp2RegInfo(typ: Longint; Op: Pointer; Var RegInfo: TRegInfo);
  811. Begin
  812. Case typ Of
  813. Top_Reg:
  814. If (TRegister(op) <> R_NO) Then
  815. AddReg2RegInfo(TRegister(op), TRegister(op), RegInfo);
  816. Top_Ref:
  817. Begin
  818. If TReference(op^).base <> R_NO Then
  819. AddReg2RegInfo(TReference(op^).base, TReference(op^).base, RegInfo);
  820. If TReference(op^).index <> R_NO Then
  821. AddReg2RegInfo(TReference(op^).index, TReference(op^).index, RegInfo);
  822. End;
  823. End;
  824. End;
  825. Function RegsEquivalent(OldReg, NewReg: TRegister; Var RegInfo: TRegInfo; OPAct: TOpAction): Boolean;
  826. Begin
  827. If Not((OldReg = R_NO) Or (NewReg = R_NO)) Then
  828. If RegsSameSize(OldReg, NewReg) Then
  829. With RegInfo Do
  830. {here we always check for the 32 bit component, because it is possible that
  831. the 8 bit component has not been set, event though NewReg already has been
  832. processed. This happens if it has been compared with a register that doesn't
  833. have an 8 bit component (such as EDI). In that case the 8 bit component is
  834. still set to R_NO and the comparison in the Else-part will fail}
  835. If (Reg32(OldReg) in OldRegsEncountered) Then
  836. If (Reg32(NewReg) in NewRegsEncountered) Then
  837. RegsEquivalent := (OldReg = New2OldReg[NewReg])
  838. { If we haven't encountered the new register yet, but we have encountered the
  839. old one already, the new one can only be correct if it's being written to
  840. (and consequently the old one is also being written to), otherwise
  841. movl -8(%ebp), %eax and movl -8(%ebp), %eax
  842. movl (%eax), %eax movl (%edx), %edx
  843. are considered equivalent}
  844. Else
  845. If (OpAct = OpAct_Write) Then
  846. Begin
  847. AddReg2RegInfo(OldReg, NewReg, RegInfo);
  848. RegsEquivalent := True
  849. End
  850. Else Regsequivalent := False
  851. Else
  852. If Not(Reg32(NewReg) in NewRegsEncountered) Then
  853. Begin
  854. AddReg2RegInfo(OldReg, NewReg, RegInfo);
  855. RegsEquivalent := True
  856. End
  857. Else RegsEquivalent := False
  858. Else RegsEquivalent := False
  859. Else RegsEquivalent := OldReg = NewReg
  860. End;
  861. Function RefsEquivalent(Const R1, R2: TReference; var RegInfo: TRegInfo; OpAct: TOpAction): Boolean;
  862. Begin
  863. If R1.IsIntValue
  864. Then RefsEquivalent := R2.IsIntValue and (R1.Offset = R2.Offset)
  865. Else If (R1.Offset = R2.Offset) And
  866. RegsEquivalent(R1.Base, R2.Base, RegInfo, OpAct) And
  867. RegsEquivalent(R1.Index, R2.Index, RegInfo, OpAct) And
  868. (R1.Segment = R2.Segment) And (R1.ScaleFactor = R2.ScaleFactor)
  869. Then
  870. Begin
  871. If Assigned(R1.Symbol)
  872. Then RefsEquivalent := Assigned(R2.Symbol) And (R1.Symbol^=R2.Symbol^)
  873. Else RefsEquivalent := Not(Assigned(R2.Symbol));
  874. End
  875. Else RefsEquivalent := False;
  876. End;
  877. Function RefsEqual(Const R1, R2: TReference): Boolean;
  878. Begin
  879. If R1.IsIntValue
  880. Then RefsEqual := R2.IsIntValue and (R1.Offset = R2.Offset)
  881. Else If (R1.Offset = R2.Offset) And (R1.Base = R2.Base) And
  882. (R1.Index = R2.Index) And (R1.Segment = R2.Segment) And
  883. (R1.ScaleFactor = R2.ScaleFactor)
  884. Then
  885. Begin
  886. If Assigned(R1.Symbol)
  887. Then RefsEqual := Assigned(R2.Symbol) And (R1.Symbol^=R2.Symbol^)
  888. Else RefsEqual := Not(Assigned(R2.Symbol));
  889. End
  890. Else RefsEqual := False;
  891. End;
  892. Function IsGP32Reg(Reg: TRegister): Boolean;
  893. {Checks if the register is a 32 bit general purpose register}
  894. Begin
  895. If (Reg >= R_EAX) and (Reg <= R_EBX)
  896. Then IsGP32Reg := True
  897. Else IsGP32reg := False
  898. End;
  899. Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
  900. Begin {checks whether Ref contains a reference to Reg}
  901. Reg := Reg32(Reg);
  902. RegInRef := (Ref.Base = Reg) Or (Ref.Index = Reg)
  903. End;
  904. Function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
  905. {checks if Reg is used by the instruction p1}
  906. Var TmpResult: Boolean;
  907. Begin
  908. TmpResult := False;
  909. If (Pai(p1)^.typ = ait_instruction) Then
  910. Begin
  911. Case Pai386(p1)^.op1t Of
  912. Top_Reg: TmpResult := Reg = TRegister(Pai386(p1)^.op1);
  913. Top_Ref: TmpResult := RegInRef(Reg, TReference(Pai386(p1)^.op1^))
  914. End;
  915. If Not(TmpResult) Then
  916. Case Pai386(p1)^.op2t Of
  917. Top_Reg:
  918. if Pai386(p1)^.op3t<>Top_reg
  919. then TmpResult := Reg = TRegister(Pai386(p1)^.op2)
  920. else TmpResult := longint(Reg) = twowords(Pai386(p1)^.op2).word1;
  921. Top_Ref: TmpResult := RegInRef(Reg, TReference(Pai386(p1)^.op2^))
  922. End;
  923. If Not(TmpResult) Then
  924. Case Pai386(p1)^.op3t Of
  925. Top_Reg: TmpResult := longint(Reg) =twowords(Pai386(p1)^.op2).word2;
  926. Top_none:;
  927. else
  928. internalerror($Da);
  929. End
  930. End;
  931. RegInInstruction := TmpResult
  932. End;
  933. {Function RegInOp(Reg: TRegister; opt: Longint; op: Pointer): Boolean;
  934. Begin
  935. RegInOp := False;
  936. Case opt Of
  937. top_reg: RegInOp := Reg = TRegister(Pointer);
  938. top_ref: RegInOp := (Reg = TReference(op^).Base) Or
  939. (Reg = TReference(op^).Index);
  940. End;
  941. End;}
  942. Function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
  943. {returns true if Reg is modified by the instruction p1. P1 is assumed to be
  944. of the type ait_instruction}
  945. Var hp: Pai;
  946. Begin
  947. If GetLastInstruction(p1, hp)
  948. Then
  949. RegModifiedByInstruction :=
  950. PPAiProp(p1^.fileinfo.line)^.Regs[Reg].WState <>
  951. PPAiProp(hp^.fileinfo.line)^.Regs[Reg].WState
  952. Else RegModifiedByInstruction := True;
  953. End;
  954. {********************* GetNext and GetLastInstruction *********************}
  955. Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
  956. {skips ait_regalloc, ait_regdealloc and ait_stab* objects and puts the
  957. next pai object in Next. Returns false if there isn't any}
  958. Begin
  959. Repeat
  960. Current := Pai(Current^.Next);
  961. While Assigned(Current) And
  962. ((Current^.typ In SkipInstr) or
  963. ((Current^.typ = ait_label) And
  964. Not(Pai_Label(Current)^.l^.is_used))) Do
  965. Current := Pai(Current^.Next);
  966. If Assigned(Current) And
  967. (Current^.typ = ait_Marker) And
  968. (Pai_Marker(Current)^.Kind = NoPropInfoStart) Then
  969. Begin
  970. While Assigned(Current) And
  971. ((Current^.typ <> ait_Marker) Or
  972. (Pai_Marker(Current)^.Kind <> NoPropInfoEnd)) Do
  973. Current := Pai(Current^.Next);
  974. End;
  975. Until Not(Assigned(Current)) Or
  976. (Current^.typ <> ait_Marker) Or
  977. (Pai_Marker(Current)^.Kind <> NoPropInfoEnd);
  978. Next := Current;
  979. If Assigned(Current) And
  980. Not((Current^.typ In SkipInstr) or
  981. ((Current^.typ = ait_label) And
  982. Not(Pai_Label(Current)^.l^.is_used)))
  983. Then GetNextInstruction := True
  984. Else
  985. Begin
  986. Next := Nil;
  987. GetNextInstruction := False;
  988. End;
  989. End;
  990. Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
  991. {skips the ait-types in SkipInstr puts the previous pai object in
  992. Last. Returns false if there isn't any}
  993. Begin
  994. Repeat
  995. Current := Pai(Current^.previous);
  996. While Assigned(Current) And
  997. ((Pai(Current)^.typ In SkipInstr) or
  998. ((Pai(Current)^.typ = ait_label) And
  999. Not(Pai_Label(Current)^.l^.is_used))) Do
  1000. Current := Pai(Current^.previous);
  1001. If Assigned(Current) And
  1002. (Current^.typ = ait_Marker) And
  1003. (Pai_Marker(Current)^.Kind = NoPropInfoEnd) Then
  1004. Begin
  1005. While Assigned(Current) And
  1006. ((Current^.typ <> ait_Marker) Or
  1007. (Pai_Marker(Current)^.Kind <> NoPropInfoStart)) Do
  1008. Current := Pai(Current^.previous);
  1009. End;
  1010. Until Not(Assigned(Current)) Or
  1011. (Current^.typ <> ait_Marker) Or
  1012. (Pai_Marker(Current)^.Kind <> NoPropInfoStart);
  1013. Last := Current;
  1014. If Assigned(Current) And
  1015. Not((Current^.typ In SkipInstr) or
  1016. ((Current^.typ = ait_label) And
  1017. Not(Pai_Label(Current)^.l^.is_used)))
  1018. Then GetLastInstruction := True
  1019. Else
  1020. Begin
  1021. Last := Nil;
  1022. GetLastInstruction := False
  1023. End;
  1024. End;
  1025. Procedure SkipHead(var P: Pai);
  1026. Var OldP: Pai;
  1027. Begin
  1028. Repeat
  1029. OldP := P;
  1030. If (P^.typ in SkipInstr) Then
  1031. GetNextInstruction(P, P)
  1032. Else If ((P^.Typ = Ait_Marker) And
  1033. (Pai_Marker(P)^.Kind = NoPropInfoStart)) Then
  1034. {a marker of the NoPropInfoStart can4t be the first instruction of a
  1035. paasmoutput list}
  1036. GetNextInstruction(Pai(P^.Previous),P);
  1037. If (P^.Typ = Ait_Marker) And
  1038. (Pai_Marker(P)^.Kind = AsmBlockStart) Then
  1039. Begin
  1040. P := Pai(P^.Next);
  1041. While (P^.typ <> Ait_Marker) Or
  1042. (Pai_Marker(P)^.Kind <> AsmBlockEnd) Do
  1043. P := Pai(P^.Next)
  1044. End;
  1045. Until P = OldP
  1046. End;
  1047. {******************* The Data Flow Analyzer functions ********************}
  1048. Procedure UpdateUsedRegs(Var UsedRegs: TRegSet; p: Pai);
  1049. {updates UsedRegs with the RegAlloc Information coming after P}
  1050. Begin
  1051. Repeat
  1052. While Assigned(p) And
  1053. ((p^.typ in (SkipInstr - [ait_RegAlloc, ait_RegDealloc])) or
  1054. ((p^.typ = ait_label) And
  1055. Not(Pai_Label(p)^.l^.is_used))) Do
  1056. p := Pai(p^.next);
  1057. While Assigned(p) And
  1058. (p^.typ in [ait_RegAlloc, ait_RegDealloc]) Do
  1059. Begin
  1060. Case p^.typ Of
  1061. ait_RegAlloc: UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg];
  1062. ait_regdealloc: UsedRegs := UsedRegs - [PaiRegDeAlloc(p)^.Reg];
  1063. End;
  1064. p := pai(p^.next);
  1065. End;
  1066. Until Not(Assigned(p)) Or
  1067. (Not(p^.typ in SkipInstr) And
  1068. Not((p^.typ = ait_label) And
  1069. Not(Pai_Label(p)^.l^.is_used)));
  1070. End;
  1071. (*Function FindZeroreg(p: Pai; Var Result: TRegister): Boolean;
  1072. {Finds a register which contains the constant zero}
  1073. Var Counter: TRegister;
  1074. Begin
  1075. Counter := R_EAX;
  1076. FindZeroReg := True;
  1077. While (Counter <= R_EDI) And
  1078. ((PPaiProp(p^.fileinfo.line)^.Regs[Counter].Typ <> Con_Const) or
  1079. (PPaiProp(p^.fileinfo.line)^.Regs[Counter].StartMod <> Pointer(0))) Do
  1080. Inc(Byte(Counter));
  1081. If (PPaiProp(p^.fileinfo.line)^.Regs[Counter].Typ = Con_Const) And
  1082. (PPaiProp(p^.fileinfo.line)^.Regs[Counter].StartMod = Pointer(0))
  1083. Then Result := Counter
  1084. Else FindZeroReg := False;
  1085. End;*)
  1086. Function TCh2Reg(Ch: TChange): TRegister;
  1087. {converts a TChange variable to a TRegister}
  1088. Begin
  1089. If (Ch <= C_REDI) Then
  1090. TCh2Reg := TRegister(Byte(Ch))
  1091. Else
  1092. If (Ch <= C_WEDI) Then
  1093. TCh2Reg := TRegister(Byte(Ch) - Byte(C_REDI))
  1094. Else
  1095. If (Ch <= C_RWEDI) Then
  1096. TCh2Reg := TRegister(Byte(Ch) - Byte(C_WEDI))
  1097. Else InternalError($db)
  1098. End;
  1099. Procedure IncState(Var S: Byte);
  1100. {Increases S by 1, wraps around at $ffff to 0 (so we won't get overflow
  1101. errors}
  1102. Begin
  1103. If (s <> $ff)
  1104. Then Inc(s)
  1105. Else s := 0
  1106. End;
  1107. Function RegInSequence(Reg: TRegister; Const Content: TContent): Boolean;
  1108. {checks the whole sequence of Content (so StartMod and and the next NrOfMods
  1109. Pai objects) to see whether Reg is used somewhere, without it being loaded
  1110. with something else first}
  1111. Var p: Pai;
  1112. Counter: Byte;
  1113. TmpResult: Boolean;
  1114. RegsChecked: TRegSet;
  1115. Begin
  1116. RegsChecked := [];
  1117. p := Content.StartMod;
  1118. TmpResult := False;
  1119. Counter := 1;
  1120. While Not(TmpResult) And
  1121. (Counter <= Content.NrOfMods) Do
  1122. Begin
  1123. If (p^.typ = ait_instruction) and
  1124. ((Pai386(p)^._operator = A_MOV) or
  1125. (Pai386(p)^._operator = A_MOVZX) or
  1126. (Pai386(p)^._operator = A_MOVSX))
  1127. Then
  1128. If (Pai386(p)^.op1t = top_ref)
  1129. Then
  1130. With TReference(Pai386(p)^.op1^) Do
  1131. If (Base = ProcInfo.FramePointer) And
  1132. (Index = R_NO)
  1133. Then RegsChecked := RegsChecked + [Reg32(TRegister(Pai386(p)^.op2))]
  1134. Else
  1135. Begin
  1136. If (Base = Reg) And
  1137. Not(Base In RegsChecked)
  1138. Then TmpResult := True;
  1139. If Not(TmpResult) And
  1140. (Index = Reg) And
  1141. Not(Index In RegsChecked)
  1142. Then TmpResult := True;
  1143. End;
  1144. Inc(Counter);
  1145. GetNextInstruction(p,p)
  1146. End;
  1147. RegInSequence := TmpResult
  1148. End;
  1149. Procedure DestroyReg(p1: PPaiProp; Reg: TRegister);
  1150. {Destroys the contents of the register Reg in the PPaiProp p1, as well as the
  1151. contents of registers are loaded with a memory location based on Reg}
  1152. Var TmpWState, TmpRState: Byte;
  1153. Counter: TRegister;
  1154. Begin
  1155. Reg := Reg32(Reg);
  1156. NrOfInstrSinceLastMod[Reg] := 0;
  1157. If (Reg >= R_EAX) And (Reg <= R_EDI)
  1158. Then
  1159. Begin
  1160. With p1^.Regs[Reg] Do
  1161. Begin
  1162. IncState(WState);
  1163. TmpWState := WState;
  1164. TmpRState := RState;
  1165. FillChar(p1^.Regs[Reg], SizeOf(TContent), 0);
  1166. WState := TmpWState;
  1167. RState := TmpRState;
  1168. End;
  1169. For Counter := R_EAX to R_EDI Do
  1170. With p1^.Regs[Counter] Do
  1171. If (Typ = Con_Ref) And
  1172. RegInSequence(Reg, p1^.Regs[Counter])
  1173. Then
  1174. Begin
  1175. IncState(WState);
  1176. TmpWState := WState;
  1177. TmpRState := RState;
  1178. FillChar(p1^.Regs[Counter], SizeOf(TContent), 0);
  1179. WState := TmpWState;
  1180. RState := TmpRState;
  1181. End;
  1182. End;
  1183. End;
  1184. {Procedure AddRegsToSet(p: Pai; Var RegSet: TRegSet);
  1185. Begin
  1186. If (p^.typ = ait_instruction) Then
  1187. Begin
  1188. Case Pai386(p)^.op1t Of
  1189. top_reg:
  1190. If Not(TRegister(Pai386(p)^.op1) in [R_NO,R_ESP,ProcInfo.FramePointer]) Then
  1191. RegSet := RegSet + [TRegister(Pai386(p)^.op1)];
  1192. top_ref:
  1193. With TReference(Pai386(p)^.op1^) Do
  1194. Begin
  1195. If Not(Base in [ProcInfo.FramePointer,R_NO,R_ESP])
  1196. Then RegSet := RegSet + [Base];
  1197. If Not(Index in [ProcInfo.FramePointer,R_NO,R_ESP])
  1198. Then RegSet := RegSet + [Index];
  1199. End;
  1200. End;
  1201. Case Pai386(p)^.op2t Of
  1202. top_reg:
  1203. If Not(TRegister(Pai386(p)^.op2) in [R_NO,R_ESP,ProcInfo.FramePointer]) Then
  1204. If RegSet := RegSet + [TRegister(TwoWords(Pai386(p)^.op2).Word1];
  1205. top_ref:
  1206. With TReference(Pai386(p)^.op2^) Do
  1207. Begin
  1208. If Not(Base in [ProcInfo.FramePointer,R_NO,R_ESP])
  1209. Then RegSet := RegSet + [Base];
  1210. If Not(Index in [ProcInfo.FramePointer,R_NO,R_ESP])
  1211. Then RegSet := RegSet + [Index];
  1212. End;
  1213. End;
  1214. End;
  1215. End;}
  1216. Function OpsEquivalent(typ: Longint; OldOp, NewOp: Pointer; Var RegInfo: TRegInfo; OpAct: TopAction): Boolean;
  1217. Begin {checks whether the two ops are equivalent}
  1218. Case typ Of
  1219. Top_Reg: OpsEquivalent :=RegsEquivalent(TRegister(OldOp), TRegister(NewOp), RegInfo, OpAct);
  1220. Top_Const: OpsEquivalent := OldOp = NewOp;
  1221. Top_Ref: OpsEquivalent := RefsEquivalent(TReference(OldOp^), TReference(NewOp^), RegInfo, OpAct);
  1222. Top_None: OpsEquivalent := True
  1223. Else OpsEquivalent := False
  1224. End;
  1225. End;
  1226. Function OpsEqual(typ: Longint; op1, op2: Pointer): Boolean;
  1227. Begin {checks whether the two ops are equal}
  1228. Case typ Of
  1229. Top_Reg, Top_Const: OpsEqual := op1 = op2;
  1230. Top_Ref: OpsEqual := RefsEqual(TReference(op1^), TReference(op2^));
  1231. Top_None: OpsEqual := True
  1232. Else OpsEqual := False
  1233. End;
  1234. End;
  1235. Function InstructionsEquivalent(p1, p2: Pai; Var RegInfo: TRegInfo): Boolean;
  1236. Begin {checks whether two Pai386 instructions are equal}
  1237. If Assigned(p1) And Assigned(p2) And
  1238. (Pai(p1)^.typ = ait_instruction) And
  1239. (Pai(p1)^.typ = ait_instruction) And
  1240. (Pai386(p1)^._operator = Pai386(p2)^._operator) And
  1241. (Pai386(p1)^.op1t = Pai386(p2)^.op1t) And
  1242. (Pai386(p1)^.op2t = Pai386(p2)^.op2t) And
  1243. (Pai386(p1)^.op3t = Pai386(p2)^.op3t)
  1244. Then
  1245. {both instructions have the same structure:
  1246. "<operator> <operand of type1>, <operand of type 2>"}
  1247. If ((Pai386(p1)^._operator = A_MOV) or
  1248. (Pai386(p1)^._operator = A_MOVZX) or
  1249. (Pai386(p1)^._operator = A_MOVSX)) And
  1250. (Pai386(p1)^.op1t = top_ref) {then op2t = top_reg} Then
  1251. If Not(RegInRef(TRegister(Pai386(p1)^.op2), TReference(Pai386(p1)^.op1^))) Then
  1252. {the "old" instruction is a load of a register with a new value, not with
  1253. a value based on the contents of this register (so no "mov (reg), reg")}
  1254. If Not(RegInRef(TRegister(Pai386(p2)^.op2), TReference(Pai386(p2)^.op1^))) And
  1255. RefsEqual(TReference(Pai386(p1)^.op1^), TReference(Pai386(p2)^.op1^))
  1256. Then
  1257. {the "new" instruction is also a load of a register with a new value, and
  1258. this value is fetched from the same memory location}
  1259. Begin
  1260. With TReference(Pai386(p2)^.op1^) Do
  1261. Begin
  1262. If Not(Base in [ProcInfo.FramePointer, R_NO, R_ESP])
  1263. {it won't do any harm if the register is already in RegsLoadedForRef}
  1264. Then RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef + [Base];
  1265. If Not(Index in [ProcInfo.FramePointer, R_NO, R_ESP])
  1266. Then RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef + [Index];
  1267. End;
  1268. {add the registers from the reference (op1) to the RegInfo, all registers
  1269. from the reference are the same in the old and in the new instruction
  1270. sequence}
  1271. AddOp2RegInfo(Pai386(p1)^.op1t, Pai386(p1)^.op1, RegInfo);
  1272. {the registers from op2 have to be equivalent, but not necessarily equal}
  1273. InstructionsEquivalent :=
  1274. RegsEquivalent(TRegister(Pai386(p1)^.op2), TRegister(Pai386(p2)^.op2),
  1275. RegInfo, OpAct_Write);
  1276. End
  1277. {the registers are loaded with values from different memory locations. If
  1278. this was allowed, the instructions "mov -4(esi),eax" and "mov -4(ebp),eax"
  1279. would be considered equivalent}
  1280. Else InstructionsEquivalent := False
  1281. Else
  1282. {load register with a value based on the current value of this register}
  1283. Begin
  1284. With TReference(Pai386(p2)^.op1^) Do
  1285. Begin
  1286. If Not(Base in [ProcInfo.FramePointer,
  1287. Reg32(TRegister(Pai386(p2)^.op2)),R_NO,R_ESP])
  1288. {it won't do any harm if the register is already in RegsLoadedForRef}
  1289. Then
  1290. Begin
  1291. RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef + [Base];
  1292. {$ifdef csdebug}
  1293. Writeln(att_reg2str[base], ' added');
  1294. {$endif csdebug}
  1295. end;
  1296. If Not(Index in [ProcInfo.FramePointer,
  1297. Reg32(TRegister(Pai386(p2)^.op2)),R_NO,R_ESP])
  1298. Then
  1299. Begin
  1300. RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef + [Index];
  1301. {$ifdef csdebug}
  1302. Writeln(att_reg2str[index], ' added');
  1303. {$endif csdebug}
  1304. end;
  1305. End;
  1306. If Not(Reg32(TRegister(Pai386(p2)^.op2)) In [ProcInfo.FramePointer,
  1307. R_NO,R_ESP])
  1308. Then
  1309. Begin
  1310. RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef -
  1311. [Reg32(TRegister(Pai386(p2)^.op2))];
  1312. {$ifdef csdebug}
  1313. Writeln(att_reg2str[Reg32(TRegister(Pai386(p2)^.op2))], ' removed');
  1314. {$endif csdebug}
  1315. end;
  1316. InstructionsEquivalent :=
  1317. OpsEquivalent(Pai386(p1)^.op1t, Pai386(p1)^.op1, Pai386(p2)^.op1, RegInfo, OpAct_Read) And
  1318. OpsEquivalent(Pai386(p1)^.op2t, Pai386(p1)^.op2, Pai386(p2)^.op2, RegInfo, OpAct_Write)
  1319. End
  1320. Else
  1321. {an instruction <> mov, movzx, movsx}
  1322. If (Pai386(p1)^.op3t = top_none) Then
  1323. InstructionsEquivalent :=
  1324. OpsEquivalent(Pai386(p1)^.op1t, Pai386(p1)^.op1, Pai386(p2)^.op1, RegInfo, OpAct_Unknown) And
  1325. OpsEquivalent(Pai386(p1)^.op2t, Pai386(p1)^.op2, Pai386(p2)^.op2, RegInfo, OpAct_Unknown)
  1326. Else
  1327. InstructionsEquivalent :=
  1328. OpsEquivalent(Pai386(p1)^.op1t, Pai386(p1)^.op1, Pai386(p2)^.op1, RegInfo, OpAct_Unknown) And
  1329. OpsEquivalent(Pai386(p1)^.op2t, Pointer(Longint(TwoWords(Pai386(p1)^.op2).Word1)),
  1330. Pointer(Longint(TwoWords(Pai386(p2)^.op2).Word1)), RegInfo, OpAct_Unknown) And
  1331. OpsEquivalent(Pai386(p1)^.op3t, Pointer(Longint(TwoWords(Pai386(p1)^.op2).Word2)),
  1332. Pointer(Longint(TwoWords(Pai386(p2)^.op2).Word2)), RegInfo, OpAct_Unknown)
  1333. {the instructions haven't even got the same structure, so they're certainly
  1334. not equivalent}
  1335. Else InstructionsEquivalent := False;
  1336. End;
  1337. (*
  1338. Function InstructionsEqual(p1, p2: Pai): Boolean;
  1339. Begin {checks whether two Pai386 instructions are equal}
  1340. InstructionsEqual :=
  1341. Assigned(p1) And Assigned(p2) And
  1342. ((Pai(p1)^.typ = ait_instruction) And
  1343. (Pai(p1)^.typ = ait_instruction) And
  1344. (Pai386(p1)^._operator = Pai386(p2)^._operator) And
  1345. (Pai386(p1)^.op1t = Pai386(p2)^.op1t) And
  1346. (Pai386(p1)^.op2t = Pai386(p2)^.op2t) And
  1347. OpsEqual(Pai386(p1)^.op1t, Pai386(p1)^.op1, Pai386(p2)^.op1) And
  1348. OpsEqual(Pai386(p1)^.op2t, Pai386(p1)^.op2, Pai386(p2)^.op2))
  1349. End;
  1350. *)
  1351. Function RefInInstruction(Const Ref: TReference; p: Pai): Boolean;
  1352. {checks whehter Ref is used in P}
  1353. Var TmpResult: Boolean;
  1354. Begin
  1355. TmpResult := False;
  1356. If (p^.typ = ait_instruction) Then
  1357. Begin
  1358. If (Pai386(p)^.op1t = Top_Ref)
  1359. Then TmpResult := RefsEqual(Ref, TReference(Pai386(p)^.op1^));
  1360. If Not(TmpResult) And
  1361. (Pai386(p)^.op2t = Top_Ref)
  1362. Then TmpResult := RefsEqual(Ref, TReference(Pai386(p)^.op2^));
  1363. End;
  1364. RefInInstruction := TmpResult;
  1365. End;
  1366. Function RefInSequence(Const Ref: TReference; Content: TContent): Boolean;
  1367. {checks the whole sequence of Content (so StartMod and and the next NrOfMods
  1368. Pai objects) to see whether Ref is used somewhere}
  1369. Var p: Pai;
  1370. Counter: Byte;
  1371. TmpResult: Boolean;
  1372. Begin
  1373. p := Content.StartMod;
  1374. TmpResult := False;
  1375. Counter := 1;
  1376. While Not(TmpResult) And
  1377. (Counter <= Content.NrOfMods) Do
  1378. Begin
  1379. If (p^.typ = ait_instruction) And
  1380. RefInInstruction(Ref, p)
  1381. Then TmpResult := True;
  1382. Inc(Counter);
  1383. GetNextInstruction(p,p)
  1384. End;
  1385. RefInSequence := TmpResult
  1386. End;
  1387. Procedure DestroyRefs(p: pai; Const Ref: TReference; WhichReg: TRegister);
  1388. {destroys all registers which possibly contain a reference to Ref, WhichReg
  1389. is the register whose contents are being written to memory (if this proc
  1390. is called because of a "mov?? %reg, (mem)" instruction)}
  1391. Var Counter: TRegister;
  1392. Begin
  1393. WhichReg := Reg32(WhichReg);
  1394. If ((Ref.base = ProcInfo.FramePointer) And
  1395. (Ref.Index = R_NO)) Or
  1396. Assigned(Ref.Symbol)
  1397. Then
  1398. {write something to a parameter, a local or global variable, so
  1399. * with uncertzain optimizations on:
  1400. - destroy the contents of registers whose contents have somewhere a
  1401. "mov?? (Ref), %reg". WhichReg (this is the register whose contents
  1402. are being written to memory) is not destroyed if it's StartMod is
  1403. of that form and NrOfMods = 1 (so if it holds ref, but is not a
  1404. pointer based on Ref)
  1405. * with uncertain optimizations off:
  1406. - also destroy registers that contain any pointer}
  1407. For Counter := R_EAX to R_EDI Do
  1408. With PPaiProp(p^.fileinfo.line)^.Regs[Counter] Do
  1409. Begin
  1410. If (typ = Con_Ref) And
  1411. (Not(cs_UncertainOpts in aktglobalswitches) And
  1412. (NrOfMods <> 1)
  1413. ) Or
  1414. (RefInSequence(Ref,PPaiProp(p^.fileinfo.line)^.Regs[Counter]) And
  1415. ((Counter <> WhichReg) Or
  1416. ((NrOfMods = 1) And
  1417. {StarMod is always of the type ait_instruction}
  1418. (Pai386(StartMod)^.op1t = top_ref) And
  1419. RefsEqual(TReference(Pai386(StartMod)^.op1^), Ref)
  1420. )
  1421. )
  1422. )
  1423. Then DestroyReg(PPaiProp(p^.fileinfo.line), Counter)
  1424. End
  1425. Else
  1426. {write something to a pointer location, so
  1427. * with uncertain optimzations on:
  1428. - do not destroy registers which contain a local/global variable or a
  1429. parameter, except if DestroyRefs is called because of a "movsl"
  1430. * with uncertain optimzations off:
  1431. - destroy every register which contains a memory location
  1432. }
  1433. For Counter := R_EAX to R_EDI Do
  1434. With PPaiProp(p^.fileinfo.line)^.Regs[Counter] Do
  1435. If (typ = Con_Ref) And
  1436. (Not(cs_UncertainOpts in aktglobalswitches) Or
  1437. {for movsl}
  1438. (Ref.Base = R_EDI) Or
  1439. {don't destroy if reg contains a parameter, local or global variable}
  1440. Not((NrOfMods = 1) And
  1441. (Pai386(StartMod)^.op1t = top_ref) And
  1442. ((PReference(Pai386(StartMod)^.op1)^.base = ProcInfo.FramePointer) Or
  1443. Assigned(PReference(Pai386(StartMod)^.op1)^.Symbol)
  1444. )
  1445. )
  1446. )
  1447. Then DestroyReg(PPaiProp(p^.FileInfo.Line), Counter)
  1448. End;
  1449. Procedure DestroyAllRegs(p: PPaiProp);
  1450. Var Counter: TRegister;
  1451. Begin {initializes/desrtoys all registers}
  1452. For Counter := R_EAX To R_EDI Do
  1453. DestroyReg(p, Counter);
  1454. p^.DirFlag := F_Unknown;
  1455. End;
  1456. Procedure Destroy(PaiObj: Pai; Opt: Longint; Op: Pointer);
  1457. Begin
  1458. Case Opt Of
  1459. top_reg: DestroyReg(PPaiProp(PaiObj^.fileinfo.line), TRegister(Op));
  1460. top_ref: DestroyRefs(PaiObj, TReference(Op^), R_NO);
  1461. top_symbol:;
  1462. End;
  1463. End;
  1464. Procedure ReadReg(p: PPaiProp; Reg: TRegister);
  1465. Begin
  1466. IncState(p^.Regs[Reg32(Reg)].RState)
  1467. End;
  1468. Procedure ReadRef(p: PPaiProp; Ref: PReference);
  1469. Begin
  1470. If Ref^.Base <> R_NO Then
  1471. ReadReg(p, Ref^.Base);
  1472. If Ref^.Index <> R_NO Then
  1473. ReadReg(p, Ref^.Index);
  1474. End;
  1475. Procedure ReadOp(P: PPaiProp; opt: Longint; Op: Pointer);
  1476. Begin
  1477. Case Opt Of
  1478. top_reg: ReadReg(P, TRegister(Op));
  1479. top_ref: ReadRef(P, PReference(Op));
  1480. top_symbol:
  1481. End;
  1482. End;
  1483. Function DFAPass1(AsmL: PAasmOutput; BlockStart: Pai): Pai;
  1484. {gathers the RegAlloc data... still need to think about where to store it to
  1485. avoid global vars}
  1486. Var BlockEnd: Pai;
  1487. Begin
  1488. BlockEnd := FindLoHiLabels(AsmL, LoLab, HiLab, LabDif, BlockStart);
  1489. BuildLabelTableAndFixRegAlloc(AsmL, LTable, LoLab, LabDif, BlockStart, BlockEnd);
  1490. DFAPass1 := BlockEnd;
  1491. End;
  1492. Procedure DoDFAPass2(
  1493. {$Ifdef StateDebug}
  1494. AsmL: PAasmOutput;
  1495. {$endif statedebug}
  1496. BlockStart, BlockEnd: Pai);
  1497. {Analyzes the Data Flow of an assembler list. Starts creating the reg
  1498. contents for the instructions starting with p. Returns the last pai which has
  1499. been processed}
  1500. Var
  1501. CurProp: PPaiProp;
  1502. {$ifdef AnalyzeLoops}
  1503. TmpState: Byte;
  1504. {$endif AnalyzeLoops}
  1505. Cnt, InstrCnt : Longint;
  1506. InstrProp: TAsmInstrucProp;
  1507. UsedRegs: TRegSet;
  1508. p, hp : Pai;
  1509. TmpRef: TReference;
  1510. TmpReg: TRegister;
  1511. Begin
  1512. p := BlockStart;
  1513. UsedRegs := [];
  1514. UpdateUsedregs(UsedRegs, p);
  1515. If (BlockStart^.typ in SkipInstr) Then
  1516. GetNextInstruction(p, p);
  1517. BlockStart := p;
  1518. InstrCnt := 1;
  1519. FillChar(NrOfInstrSinceLastMod, SizeOf(NrOfInstrSinceLastMod), 0);
  1520. While (P <> BlockEnd) Do
  1521. Begin
  1522. {$IfDef TP}
  1523. New(CurProp);
  1524. {$Else TP}
  1525. CurProp := @PaiPropBlock^[InstrCnt];
  1526. {$EndIf TP}
  1527. If (p <> BlockStart)
  1528. Then
  1529. Begin
  1530. {$ifdef JumpAnal}
  1531. If (p^.Typ <> ait_label) Then
  1532. {$endif JumpAnal}
  1533. Begin
  1534. GetLastInstruction(p, hp);
  1535. CurProp^.Regs := PPaiProp(hp^.fileinfo.line)^.Regs;
  1536. CurProp^.DirFlag := PPaiProp(hp^.fileinfo.line)^.DirFlag;
  1537. End
  1538. End
  1539. Else
  1540. Begin
  1541. FillChar(CurProp^, SizeOf(CurProp^), 0);
  1542. { For TmpReg := R_EAX to R_EDI Do
  1543. CurProp^.Regs[TmpReg].WState := 1;}
  1544. End;
  1545. CurProp^.UsedRegs := UsedRegs;
  1546. CurProp^.CanBeRemoved := False;
  1547. UpdateUsedRegs(UsedRegs, Pai(p^.Next));
  1548. {$ifdef TP}
  1549. CurProp^.linesave := p^.fileinfo.line;
  1550. PPaiProp(p^.fileinfo.line) := CurProp;
  1551. {$Endif TP}
  1552. For TmpReg := R_EAX To R_EDI Do
  1553. Inc(NrOfInstrSinceLastMod[TmpReg]);
  1554. Case p^.typ Of
  1555. ait_label:
  1556. {$Ifndef JumpAnal}
  1557. If (Pai_label(p)^.l^.is_used) Then
  1558. DestroyAllRegs(CurProp);
  1559. {$Else JumpAnal}
  1560. Begin
  1561. If (Pai_Label(p)^.is_used) Then
  1562. With LTable^[Pai_Label(p)^.l^.nb-LoLab] Do
  1563. {$IfDef AnalyzeLoops}
  1564. If (RefsFound = Pai_Label(p)^.l^.RefCount)
  1565. {$Else AnalyzeLoops}
  1566. If (JmpsProcessed = Pai_Label(p)^.l^.RefCount)
  1567. {$EndIf AnalyzeLoops}
  1568. Then
  1569. {all jumps to this label have been found}
  1570. {$IfDef AnalyzeLoops}
  1571. If (JmpsProcessed > 0)
  1572. Then
  1573. {$EndIf AnalyzeLoops}
  1574. {we've processed at least one jump to this label}
  1575. Begin
  1576. If (GetLastInstruction(p, hp) And
  1577. Not(((hp^.typ = ait_labeled_instruction) or
  1578. (hp^.typ = ait_instruction)) And
  1579. (Pai_Labeled(hp)^._operator = A_JMP))
  1580. Then
  1581. {previous instruction not a JMP -> the contents of the registers after the
  1582. previous intruction has been executed have to be taken into account as well}
  1583. For TmpReg := R_EAX to R_EDI Do
  1584. Begin
  1585. If (CurProp^.Regs[TmpReg].WState <>
  1586. PPaiProp(hp^.FileInfo.Line)^.Regs[TmpReg].WState)
  1587. Then DestroyReg(CurProp, TmpReg)
  1588. End
  1589. End
  1590. {$IfDef AnalyzeLoops}
  1591. Else
  1592. {a label from a backward jump (e.g. a loop), no jump to this label has
  1593. already been processed}
  1594. If GetLastInstruction(p, hp) And
  1595. Not(hp^.typ = ait_labeled_instruction) And
  1596. (Pai_Labeled(hp)^._operator = A_JMP))
  1597. Then
  1598. {previous instruction not a jmp, so keep all the registers' contents from the
  1599. previous instruction}
  1600. Begin
  1601. CurProp^.Regs := PPaiProp(hp^.FileInfo.Line)^.Regs;
  1602. CurProp^.DirFlag := PPaiProp(hp^.FileInfo.Line)^.DirFlag;
  1603. End
  1604. Else
  1605. {previous instruction a jmp and no jump to this label processed yet}
  1606. Begin
  1607. hp := p;
  1608. Cnt := InstrCnt;
  1609. {continue until we find a jump to the label or a label which has already
  1610. been processed}
  1611. While GetNextInstruction(hp, hp) And
  1612. Not((hp^.typ = ait_labeled_instruction) And
  1613. (Pai_Labeled(hp)^.lab^.nb = Pai_Label(p)^.l^.nb)) And
  1614. Not((hp^.typ = ait_label) And
  1615. (LTable^[Pai_Label(hp)^.l^.nb-LoLab].RefsFound
  1616. = Pai_Label(hp)^.l^.RefCount) And
  1617. (LTable^[Pai_Label(hp)^.l^.nb-LoLab].JmpsProcessed > 0)) Do
  1618. Inc(Cnt);
  1619. If (hp^.typ = ait_label)
  1620. Then
  1621. {there's a processed label after the current one}
  1622. Begin
  1623. CurProp^.Regs := PaiPropBlock^[Cnt].Regs;
  1624. CurProp^.DirFlag := PaiPropBlock^[Cnt].DirFlag;
  1625. End
  1626. Else
  1627. {there's no label anymore after the current one, or they haven't been
  1628. processed yet}
  1629. Begin
  1630. GetLastInstruction(p, hp);
  1631. CurProp^.Regs := PPaiProp(hp^.FileInfo.Line)^.Regs;
  1632. CurProp^.DirFlag := PPaiProp(hp^.FileInfo.Line)^.DirFlag;
  1633. DestroyAllRegs(PPaiProp(hp^.FileInfo.Line))
  1634. End
  1635. End
  1636. {$EndIf AnalyzeLoops}
  1637. Else
  1638. {not all references to this label have been found, so destroy all registers}
  1639. Begin
  1640. GetLastInstruction(p, hp);
  1641. CurProp^.Regs := PPaiProp(hp^.FileInfo.Line)^.Regs;
  1642. CurProp^.DirFlag := PPaiProp(hp^.FileInfo.Line)^.DirFlag;
  1643. DestroyAllRegs(CurProp)
  1644. End;
  1645. End;
  1646. {$EndIf JumpAnal}
  1647. ait_labeled_instruction:
  1648. {$IfNDef JumpAnal}
  1649. ;
  1650. {$Else JumpAnal}
  1651. With LTable^[Pai_Labeled(p)^.lab^.nb-LoLab] Do
  1652. If (RefsFound = Pai_Labeled(p)^.lab^.RefCount) Then
  1653. Begin
  1654. If (InstrCnt < InstrNr)
  1655. Then
  1656. {forward jump}
  1657. If (JmpsProcessed = 0) Then
  1658. {no jump to this label has been processed yet}
  1659. Begin
  1660. PaiPropBlock^[InstrNr].Regs := CurProp^.Regs;
  1661. PaiPropBlock^[InstrNr].DirFlag := CurProp^.DirFlag;
  1662. Inc(JmpsProcessed);
  1663. End
  1664. Else
  1665. Begin
  1666. For TmpReg := R_EAX to R_EDI Do
  1667. If (PaiPropBlock^[InstrNr].Regs[TmpReg].WState <>
  1668. CurProp^.Regs[TmpReg].WState) Then
  1669. DestroyReg(@PaiPropBlock^[InstrNr], TmpReg);
  1670. Inc(JmpsProcessed);
  1671. End
  1672. {$ifdef AnalyzeLoops}
  1673. Else
  1674. { backward jump, a loop for example}
  1675. { If (JmpsProcessed > 0) Or
  1676. Not(GetLastInstruction(PaiObj, hp) And
  1677. (hp^.typ = ait_labeled_instruction) And
  1678. (Pai_Labeled(hp)^._operator = A_JMP))
  1679. Then}
  1680. {instruction prior to label is not a jmp, or at least one jump to the label
  1681. has yet been processed}
  1682. Begin
  1683. Inc(JmpsProcessed);
  1684. For TmpReg := R_EAX to R_EDI Do
  1685. If (PaiPropBlock^[InstrNr].Regs[TmpReg].WState <>
  1686. CurProp^.Regs[TmpReg].WState)
  1687. Then
  1688. Begin
  1689. TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
  1690. Cnt := InstrNr;
  1691. While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
  1692. Begin
  1693. DestroyReg(@PaiPropBlock^[Cnt], TmpReg);
  1694. Inc(Cnt);
  1695. End;
  1696. While (Cnt <= InstrCnt) Do
  1697. Begin
  1698. Inc(PaiPropBlock^[Cnt].Regs[TmpReg].WState);
  1699. Inc(Cnt)
  1700. End
  1701. End;
  1702. End
  1703. { Else }
  1704. {instruction prior to label is a jmp and no jumps to the label have yet been
  1705. processed}
  1706. { Begin
  1707. Inc(JmpsProcessed);
  1708. For TmpReg := R_EAX to R_EDI Do
  1709. Begin
  1710. TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
  1711. Cnt := InstrNr;
  1712. While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
  1713. Begin
  1714. PaiPropBlock^[Cnt].Regs[TmpReg] := CurProp^.Regs[TmpReg];
  1715. Inc(Cnt);
  1716. End;
  1717. TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
  1718. While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
  1719. Begin
  1720. DestroyReg(@PaiPropBlock^[Cnt], TmpReg);
  1721. Inc(Cnt);
  1722. End;
  1723. While (Cnt <= InstrCnt) Do
  1724. Begin
  1725. Inc(PaiPropBlock^[Cnt].Regs[TmpReg].WState);
  1726. Inc(Cnt)
  1727. End
  1728. End
  1729. End}
  1730. {$endif AnalyzeLoops}
  1731. End;
  1732. {$EndIf JumpAnal}
  1733. {$ifdef GDB}
  1734. ait_stabs, ait_stabn, ait_stab_function_name:;
  1735. {$endif GDB}
  1736. ait_instruction:
  1737. Begin
  1738. InstrProp := AsmInstr[Pai386(p)^._operator];
  1739. Case Pai386(p)^._operator Of
  1740. A_MOV, A_MOVZX, A_MOVSX:
  1741. Begin
  1742. Case Pai386(p)^.op1t Of
  1743. Top_Reg:
  1744. Case Pai386(p)^.op2t Of
  1745. Top_Reg:
  1746. Begin
  1747. DestroyReg(CurProp, TRegister(Pai386(p)^.op2));
  1748. ReadReg(CurProp, TRegister(Pai386(p)^.op1));
  1749. { CurProp^.Regs[TRegister(Pai386(p)^.op2)] :=
  1750. CurProp^.Regs[TRegister(Pai386(p)^.op1)];
  1751. If (CurProp^.Regs[TRegister(Pai386(p)^.op2)].ModReg = R_NO) Then
  1752. CurProp^.Regs[TRegister(Pai386(p)^.op2)].ModReg :=
  1753. Tregister(Pai386(p)^.op1);}
  1754. End;
  1755. Top_Ref:
  1756. Begin
  1757. ReadReg(CurProp, TRegister(Pai386(p)^.op1));
  1758. ReadRef(CurProp, PReference(Pai386(p)^.op2));
  1759. DestroyRefs(p, TReference(Pai386(p)^.op2^), TRegister(Pai386(p)^.op1));
  1760. End;
  1761. End;
  1762. Top_Ref:
  1763. Begin {destination is always a register in this case}
  1764. ReadRef(CurProp, PReference(Pai386(p)^.op1));
  1765. ReadReg(CurProp, TRegister(Pai386(p)^.Op2));
  1766. TmpReg := Reg32(TRegister(Pai386(p)^.op2));
  1767. If RegInRef(TmpReg, TReference(Pai386(p)^.op1^)) And
  1768. (CurProp^.Regs[TmpReg].Typ = Con_Ref)
  1769. Then
  1770. Begin
  1771. With CurProp^.Regs[TmpReg] Do
  1772. Begin
  1773. IncState(WState);
  1774. {also store how many instructions are part of the sequence in the first
  1775. instructions PPaiProp, so it can be easily accessed from within
  1776. CheckSequence}
  1777. Inc(NrOfMods, NrOfInstrSinceLastMod[TmpReg]);
  1778. PPaiProp(Pai(StartMod)^.fileinfo.line)^.Regs[TmpReg].NrOfMods := NrOfMods;
  1779. NrOfInstrSinceLastMod[TmpReg] := 0;
  1780. End;
  1781. End
  1782. Else
  1783. Begin
  1784. DestroyReg(CurProp, TmpReg);
  1785. If Not(RegInRef(TmpReg, TReference(Pai386(p)^.op1^))) Then
  1786. With CurProp^.Regs[TmpReg] Do
  1787. Begin
  1788. Typ := Con_Ref;
  1789. StartMod := p;
  1790. NrOfMods := 1;
  1791. End
  1792. End;
  1793. {$ifdef StateDebug}
  1794. hp := new(pai_asm_comment,init(strpnew(att_reg2str[TmpReg]+': '+tostr(CurProp^.Regs[TmpReg].WState))));
  1795. InsertLLItem(AsmL, p, p^.next, hp);
  1796. {$endif StateDebug}
  1797. End;
  1798. Top_Const:
  1799. Begin
  1800. Case Pai386(p)^.op2t Of
  1801. Top_Reg:
  1802. Begin
  1803. TmpReg := Reg32(TRegister(Pai386(p)^.op2));
  1804. With CurProp^.Regs[TmpReg] Do
  1805. Begin
  1806. DestroyReg(CurProp, TmpReg);
  1807. typ := Con_Const;
  1808. StartMod := Pai386(p)^.op1;
  1809. End
  1810. End;
  1811. Top_Ref:
  1812. Begin
  1813. ReadRef(CurProp, PReference(Pai386(p)^.op2));
  1814. DestroyRefs(P, TReference(Pai386(p)^.op2^), R_NO);
  1815. End;
  1816. End;
  1817. End;
  1818. End;
  1819. End;
  1820. A_IMUL:
  1821. Begin
  1822. ReadOp(CurProp, Pai386(p)^.Op1t, Pai386(p)^.Op1);
  1823. If (Pai386(p)^.Op2t = Top_Ref) Then
  1824. ReadOp(CurProp, Pai386(p)^.Op2t, Pai386(p)^.Op2)
  1825. Else ReadOp(CurProp, Pai386(p)^.Op2t, Pointer(Longint(TwoWords(Pai386(p)^.Op2).Word1)));
  1826. ReadOp(CurProp, Pai386(p)^.Op3t, Pointer(LongInt(TwoWords(Pai386(p)^.Op2).Word2)));
  1827. If (Pai386(p)^.Op3t = top_none)
  1828. Then
  1829. If (Pai386(p)^.Op2t = top_none)
  1830. Then
  1831. Begin
  1832. DestroyReg(CurProp, R_EAX);
  1833. DestroyReg(CurProp, R_EDX)
  1834. End
  1835. Else Destroy(p, Pai386(p)^.Op2t, Pai386(p)^.Op2)
  1836. Else DestroyReg(CurProp, TRegister(longint(twowords(Pai386(p)^.Op2).word2)));
  1837. End;
  1838. A_XOR:
  1839. Begin
  1840. ReadOp(CurProp, Pai386(p)^.Op1t, Pai386(p)^.Op1);
  1841. ReadOp(CurProp, Pai386(p)^.Op2t, Pai386(p)^.Op2);
  1842. If (Pai386(p)^.op1t = top_reg) And
  1843. (Pai386(p)^.op2t = top_reg) And
  1844. (Pai386(p)^.op1 = Pai386(p)^.op2)
  1845. Then
  1846. Begin
  1847. DestroyReg(CurProp, Tregister(Pai386(p)^.op1));
  1848. CurProp^.Regs[Reg32(Tregister(Pai386(p)^.op1))].typ := Con_Const;
  1849. CurProp^.Regs[Reg32(Tregister(Pai386(p)^.op1))].StartMod := Pointer(0)
  1850. End
  1851. Else Destroy(p, Pai386(p)^.op2t, Pai386(p)^.op2);
  1852. End
  1853. Else
  1854. Begin
  1855. Cnt := 1;
  1856. While (Cnt <= MaxCh) And
  1857. (InstrProp.Ch[Cnt] <> C_None) Do
  1858. Begin
  1859. Case InstrProp.Ch[Cnt] Of
  1860. C_REAX..C_REDI: ReadReg(CurProp,TCh2Reg(InstrProp.Ch[Cnt]));
  1861. C_WEAX..C_RWEDI:
  1862. Begin
  1863. If (InstrProp.Ch[Cnt] >= C_RWEAX) Then
  1864. ReadReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]));
  1865. DestroyReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]));
  1866. End;
  1867. C_CDirFlag: CurProp^.DirFlag := F_NotSet;
  1868. C_SDirFlag: CurProp^.DirFlag := F_Set;
  1869. C_ROp1: ReadOp(CurProp, Pai386(p)^.op1t, Pai386(p)^.op1);
  1870. C_ROp2: If (Pai386(p)^.Op3t = top_none) Then
  1871. ReadOp(CurProp, Pai386(p)^.op2t, Pai386(p)^.op2)
  1872. Else ReadOp(CurProp, Pai386(p)^.op2t, Pointer(Longint(TwoWords(Pai386(p)^.op2).word1)));
  1873. C_ROp3: ReadOp(CurProp, Pai386(p)^.op3t, Pointer(Longint(TwoWords(Pai386(p)^.op2).word2)));
  1874. C_WOp1..C_RWOp1:
  1875. Begin
  1876. If (InstrProp.Ch[Cnt] = C_RWOp1) Then
  1877. ReadOp(CurProp, Pai386(p)^.op1t, Pai386(p)^.op1);
  1878. Destroy(p, Pai386(p)^.op1t, Pai386(p)^.op1);
  1879. End;
  1880. C_WOp2..C_RWOp2:
  1881. Begin
  1882. If (InstrProp.Ch[Cnt] = C_RWOp2) Then
  1883. If (Pai386(p)^.Op3t = top_none) Then
  1884. ReadOp(CurProp, Pai386(p)^.op2t, Pai386(p)^.op2)
  1885. Else ReadOp(CurProp, Pai386(p)^.op2t, Pointer(Longint(TwoWords(Pai386(p)^.op2).word1)));
  1886. If (Pai386(p)^.Op3t = top_none) Then
  1887. Destroy(p, Pai386(p)^.op2t, Pai386(p)^.op2)
  1888. Else Destroy(p, Pai386(p)^.op2t, Pointer(Longint(TwoWords(Pai386(p)^.op2).word1)));
  1889. End;
  1890. C_WOp3..C_RWOp3:
  1891. Begin
  1892. If (InstrProp.Ch[Cnt] = C_RWOp3) Then
  1893. ReadOp(CurProp, Pai386(p)^.op3t, Pointer(Longint(TwoWords(Pai386(p)^.op2).word2)));
  1894. Destroy(p, Pai386(p)^.op3t, Pointer(Longint(TwoWords(Pai386(p)^.op2).word2)));
  1895. End;
  1896. C_WMemEDI:
  1897. Begin
  1898. ReadReg(CurProp, R_EDI);
  1899. FillChar(TmpRef, SizeOf(TmpRef), 0);
  1900. TmpRef.Base := R_EDI;
  1901. DestroyRefs(p, TmpRef, R_NO)
  1902. End;
  1903. C_RFlags, C_WFlags, C_RWFlags, C_FPU:
  1904. Else
  1905. Begin
  1906. DestroyAllRegs(CurProp);
  1907. End;
  1908. End;
  1909. Inc(Cnt);
  1910. End
  1911. End;
  1912. End;
  1913. End
  1914. Else
  1915. Begin
  1916. DestroyAllRegs(CurProp);
  1917. End;
  1918. End;
  1919. Inc(InstrCnt);
  1920. GetNextInstruction(p, p);
  1921. End;
  1922. End;
  1923. Function InitDFAPass2(AsmL: PAasmOutput; BlockStart, BlockEnd: Pai): Boolean;
  1924. {reserves memory for the PPaiProps in one big memory block when not using
  1925. TP, returns False if not enough memory is available for the optimizer in all
  1926. cases}
  1927. Var p: Pai;
  1928. Count: Longint;
  1929. { TmpStr: String; }
  1930. Begin
  1931. P := BlockStart;
  1932. SkipHead(P);
  1933. NrOfPaiObjs := 0;
  1934. While (P <> BlockEnd) Do
  1935. Begin
  1936. {$IfDef JumpAnal}
  1937. Case P^.Typ Of
  1938. ait_labeled_instruction:
  1939. begin
  1940. If (Pai_Labeled(P)^.lab^.nb >= LoLab) And
  1941. (Pai_Labeled(P)^.lab^.nb <= HiLab) Then
  1942. Inc(LTable^[Pai_Labeled(P)^.lab^.nb-LoLab].RefsFound);
  1943. end;
  1944. ait_label:
  1945. Begin
  1946. If (Pai_Label(p)^.l^.is_used) Then
  1947. LTable^[Pai_Label(P)^.l^.nb-LoLab].InstrNr := NrOfPaiObjs
  1948. End;
  1949. { ait_instruction:
  1950. Begin
  1951. If (Pai386(p)^._operator = A_PUSH) And
  1952. (Pai386(p)^.op1t = top_symbol) And
  1953. (PCSymbol(Pai386(p)^.op1)^.offset = 0) Then
  1954. Begin
  1955. TmpStr := StrPas(PCSymbol(Pai386(p)^.op1)^.symbol);
  1956. If}
  1957. End;
  1958. {$EndIf JumpAnal}
  1959. Inc(NrOfPaiObjs);
  1960. GetNextInstruction(p, p);
  1961. End;
  1962. {$IfDef TP}
  1963. If (MemAvail < (SizeOf(TPaiProp)*NrOfPaiObjs))
  1964. Or (NrOfPaiObjs = 0)
  1965. {this doesn't have to be one contiguous block}
  1966. Then InitDFAPass2 := False
  1967. Else InitDFAPass2 := True;
  1968. {$Else}
  1969. {Uncomment the next line to see how much memory the reloading optimizer needs}
  1970. { Writeln((NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4)));}
  1971. {no need to check mem/maxavail, we've got as much virtual memory as we want}
  1972. If NrOfPaiObjs <> 0 Then
  1973. Begin
  1974. InitDFAPass2 := True;
  1975. GetMem(PaiPropBlock, NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4));
  1976. p := BlockStart;
  1977. SkipHead(p);
  1978. For Count := 1 To NrOfPaiObjs Do
  1979. Begin
  1980. PaiPropBlock^[Count].LineSave := p^.fileinfo.line;
  1981. PPaiProp(p^.fileinfo.line) := @PaiPropBlock^[Count];
  1982. GetNextInstruction(p, p);
  1983. End;
  1984. End
  1985. Else InitDFAPass2 := False;
  1986. {$EndIf TP}
  1987. End;
  1988. Function DFAPass2(AsmL: PAasmOutPut; BlockStart, BlockEnd: Pai): Boolean;
  1989. Begin
  1990. If InitDFAPass2(AsmL, BlockStart, BlockEnd) Then
  1991. Begin
  1992. DoDFAPass2(
  1993. {$ifdef statedebug}
  1994. asml,
  1995. {$endif statedebug}
  1996. BlockStart, BlockEnd);
  1997. DFAPass2 := True
  1998. End
  1999. Else DFAPass2 := False;
  2000. End;
  2001. Procedure ShutDownDFA;
  2002. Begin
  2003. If LabDif <> 0 Then
  2004. FreeMem(LTable, LabDif*SizeOf(TLabelTableItem));
  2005. End;
  2006. End.
  2007. {
  2008. $Log$
  2009. Revision 1.34 1998-12-29 18:48:19 jonas
  2010. + optimize pascal code surrounding assembler blocks
  2011. Revision 1.33 1998/12/17 16:37:38 jonas
  2012. + extra checks in RegsEquivalent so some more optimizations can be done (which
  2013. where disabled by the second fix from revision 1.22)
  2014. Revision 1.32 1998/12/15 19:33:58 jonas
  2015. * uncommented OpsEqual & added to interface because popt386 uses it now
  2016. Revision 1.31 1998/12/11 00:03:13 peter
  2017. + globtype,tokens,version unit splitted from globals
  2018. Revision 1.30 1998/12/02 16:23:39 jonas
  2019. * changed "if longintvar in set" to case or "if () or () .." statements
  2020. * tree.pas: changed inlinenumber (and associated constructor/vars) to a byte
  2021. Revision 1.29 1998/11/26 21:45:31 jonas
  2022. - removed A_CLTD opcode (use A_CDQ instead)
  2023. * changed cbw, cwde and cwd to cbtw, cwtl and cwtd in att_op2str array
  2024. * in daopt386: adapted AsmInstr array to reflect changes + fixed line too long
  2025. Revision 1.27 1998/11/24 19:47:22 jonas
  2026. * fixed problems posible with 3 operand instructions
  2027. Revision 1.26 1998/11/24 12:50:09 peter
  2028. * fixed crash
  2029. Revision 1.25 1998/11/18 17:58:22 jonas
  2030. + gathering of register reading data, nowhere used yet (necessary for instruction scheduling)
  2031. Revision 1.24 1998/11/13 10:13:44 peter
  2032. + cpuid,emms support for asm readers
  2033. Revision 1.23 1998/11/09 19:40:46 jonas
  2034. * fixed comments from last commit (apparently there's still a 255 char limit :( )
  2035. Revision 1.22 1998/11/09 19:33:40 jonas
  2036. * changed specific bugfix (which was actually wrong implemented, but
  2037. did the right thing in most cases nevertheless) to general bugfix
  2038. * fixed bug that caused
  2039. mov (ebp), edx mov (ebp), edx
  2040. mov (edx), edx mov (edx), edx
  2041. ... being changed to ...
  2042. mov (ebp), edx mov edx, eax
  2043. mov (eax), eax
  2044. but this disabled another small correct optimization...
  2045. Revision 1.21 1998/11/02 23:17:49 jonas
  2046. * fixed bug shown in sortbug program from fpc-devel list
  2047. Revision 1.20 1998/10/22 13:24:51 jonas
  2048. * changed TRegSet to a small set
  2049. Revision 1.19 1998/10/20 09:29:24 peter
  2050. * bugfix so that code like
  2051. movl 48(%esi),%esi movl 48(%esi),%esi
  2052. pushl %esi doesn't get changed to pushl %esi
  2053. movl 48(%esi),%edi movl %esi,%edi
  2054. Revision 1.18 1998/10/07 16:27:02 jonas
  2055. * changed state to WState (WriteState), added RState for future use in
  2056. instruction scheduling
  2057. * RegAlloc data from the CG is now completely being patched and corrected (I
  2058. think)
  2059. Revision 1.17 1998/10/02 17:30:20 jonas
  2060. * small patches to regdealloc data
  2061. Revision 1.16 1998/10/01 20:21:47 jonas
  2062. * inter-register CSE, still requires some tweaks (peepholeoptpass2, better RegAlloc)
  2063. Revision 1.15 1998/09/20 18:00:20 florian
  2064. * small compiling problems fixed
  2065. Revision 1.14 1998/09/20 17:12:36 jonas
  2066. * small fix for uncertain optimizations & more cleaning up
  2067. Revision 1.12 1998/09/16 18:00:01 jonas
  2068. * optimizer now completely dependant on GetNext/GetLast instruction, works again with -dRegAlloc
  2069. Revision 1.11 1998/09/15 14:05:27 jonas
  2070. * fixed optimizer incompatibilities with freelabel code in psub
  2071. Revision 1.10 1998/09/09 15:33:58 peter
  2072. * removed warnings
  2073. Revision 1.9 1998/09/03 16:24:51 florian
  2074. * bug of type conversation from dword to real fixed
  2075. * bug fix of Jonas applied
  2076. Revision 1.8 1998/08/28 10:56:59 peter
  2077. * removed warnings
  2078. Revision 1.7 1998/08/19 16:07:44 jonas
  2079. * changed optimizer switches + cleanup of DestroyRefs in daopt386.pas
  2080. Revision 1.6 1998/08/10 14:49:57 peter
  2081. + localswitches, moduleswitches, globalswitches splitting
  2082. Revision 1.5 1998/08/09 13:56:24 jonas
  2083. * small bugfix for uncertain optimizations in DestroyRefs
  2084. Revision 1.4 1998/08/06 19:40:25 jonas
  2085. * removed $ before and after Log in comment
  2086. Revision 1.3 1998/08/05 16:00:14 florian
  2087. * some fixes for ansi strings
  2088. * log to Log changed
  2089. }