daopt386.pas 92 KB

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