aoptda.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. {
  2. $Id$
  3. Copyright (c) 1999 by Jonas Maebe, member of the Free Pascal
  4. Development Team
  5. This unit contains the assembler optimizer data flow analyzer.
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. Unit aoptda;
  20. Interface
  21. uses Aasm;
  22. Type TAsmDFA = Object(TAoptCpu)
  23. Constructor Init(_AsmL: PaasmOutPut; _Blockstart, _Blockend: Pai);
  24. { returns a pointer to the LabelInfo table }
  25. Function GetLabelInfo: PLabelInfo;
  26. Destructor Done;
  27. private
  28. AsmL: PAasmOutput;
  29. LabelInfo: TLabelInfo;
  30. { How many instructions are between the current instruction and the last one }
  31. { that modified the register }
  32. NrOfInstrSinceLastMod: TInstrSinceLastMod;
  33. Procedure BuildLabelTableAndFixRegAlloc;
  34. Function FindLoHiLabels(BlockStart: Pai): Pai;
  35. End;
  36. Implementation
  37. uses aoptmsc
  38. {$ifdef i386}
  39. , ao386msc
  40. {$endif i386}
  41. ;
  42. Constructor TAsmDFA.Init(_AsmL: PaasmOutPut; _Blockstart: Pai;
  43. Var _BlockEnd: Pai);
  44. Begin
  45. AsmL := _AsmL;
  46. LabelInfo.Lowabel := High(AWord);
  47. BlockStart := _BlockStart;
  48. { initializes BlockEnd and through the methodcall also the labeltable, }
  49. { lolab, hilab and labeldif. Also, the regalloc info gets corrected. }
  50. BlockEnd := FindLoHiLabels;
  51. BuildLabelTableAndFixRegAlloc;
  52. End;
  53. Function TAsmDFA.GetLabelInfo: TLabelInfo;
  54. Begin
  55. GetLabelInfo := LabelInfo;
  56. End;
  57. Function TAsmDFA.FindLoHiLabels: Pai;
  58. { Walks through the paasmlist to find the lowest and highest label number. }
  59. { Returns the last Pai object of the current block }
  60. Var LabelFound: Boolean;
  61. P: Pai;
  62. Begin
  63. LabelFound := False;
  64. P := BlockStart;
  65. While Assigned(P) And
  66. ((P^.typ <> Ait_Marker) Or
  67. (Pai_Marker(P)^.Kind <> AsmBlockStart)) Do
  68. Begin
  69. If (Pai(p)^.typ = ait_label) Then
  70. If (Pai_Label(p)^.l^.is_used)
  71. Then
  72. Begin
  73. LabelFound := True;
  74. If (Pai_Label(p)^.l^.labelnr < LowLabel) Then
  75. LowLabel := Pai_Label(p)^.l^.labelnr;
  76. If (Pai_Label(p)^.l^.labelnr > HighLabel) Then
  77. HighLabel := Pai_Label(p)^.l^.labelnr;
  78. End;
  79. GetNextInstruction(p, p);
  80. End;
  81. FindLoHiLabels := p;
  82. If LabelFound
  83. Then LabelDif := HighLabel-LowLabel+1
  84. Else LabelDif := 0;
  85. End;
  86. Procedure TAsmDFA.BuildLabelTableAndFixRegAlloc;
  87. { Builds a table with the locations of the labels in the paasmoutput. }
  88. { Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
  89. Var p, hp1, hp2: Pai;
  90. UsedRegs: TRegSet;
  91. Begin
  92. UsedRegs := [];
  93. With LabelInfo Do
  94. If (LabelDif <> 0) Then
  95. Begin
  96. GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
  97. FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
  98. p := BlockStart;
  99. While (P <> BlockEnd) Do
  100. Begin
  101. Case p^.typ Of
  102. ait_Label:
  103. If Pai_Label(p)^.l^.is_used Then
  104. LabelTable^[Pai_Label(p)^.l^.labelnr-LowLabel].PaiObj := p;
  105. ait_regAlloc:
  106. begin
  107. if PairegAlloc(p)^.Allocation then
  108. Begin
  109. If Not(PaiRegAlloc(p)^.Reg in UsedRegs) Then
  110. UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg]
  111. Else
  112. Begin
  113. hp1 := p;
  114. hp2 := nil;
  115. While GetLastInstruction(hp1, hp1) And
  116. Not(RegInInstruction(PaiRegAlloc(p)^.Reg, hp1)) Do
  117. hp2 := hp1;
  118. If hp2 <> nil Then
  119. Begin
  120. hp1 := New(PaiRegAlloc, DeAlloc(PaiRegAlloc(p)^.Reg));
  121. InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp1);
  122. End;
  123. End;
  124. End
  125. else
  126. Begin
  127. UsedRegs := UsedRegs - [PaiRegAlloc(p)^.Reg];
  128. hp1 := p;
  129. hp2 := nil;
  130. While Not(FindRegAlloc(PaiRegAlloc(p)^.Reg, Pai(hp1^.Next))) And
  131. GetNextInstruction(hp1, hp1) And
  132. RegInInstruction(PaiRegAlloc(p)^.Reg, hp1) Do
  133. hp2 := hp1;
  134. If hp2 <> nil Then
  135. Begin
  136. hp1 := Pai(p^.previous);
  137. AsmL^.Remove(p);
  138. InsertLLItem(AsmL, hp2, Pai(hp2^.Next), p);
  139. p := hp1;
  140. End;
  141. End;
  142. end;
  143. End;
  144. P := Pai(p^.Next);
  145. While Assigned(p) And
  146. (p^.typ in (SkipInstr - [ait_regalloc])) Do
  147. P := Pai(P^.Next);
  148. End;
  149. End;
  150. Destructor TAsmDFA.Done;
  151. Begin
  152. If Assigned(LabelInfo.LabelTable) Then Dispose(LabelInfo.LabelTable);
  153. End;
  154. Procedure TAsmOptimizer.DoDFAPass2;
  155. { Analyzes the Data Flow of an assembler list. Analyses the reg contents }
  156. { for the instructions between blockstart and blockend. Returns the last pai }
  157. { which has been processed }
  158. Var
  159. CurProp: PPaiProp;
  160. Cnt, InstrCnt : Longint;
  161. InstrProp: TAsmInstrucProp;
  162. UsedRegs: TRegSet;
  163. p, hp, NewBlockStart : Pai;
  164. TmpRef: TReference;
  165. TmpReg: TRegister;
  166. {$ifdef AnalyzeLoops}
  167. TmpState: Byte;
  168. {$endif AnalyzeLoops}
  169. Begin
  170. p := BlockStart;
  171. UsedRegs.init;
  172. UsedRegs.Update(p);
  173. NewBlockStart := SkipHead(p);
  174. InstrCnt := 1;
  175. { done implicitely by the constructor
  176. FillChar(NrOfInstrSinceLastMod, SizeOf(NrOfInstrSinceLastMod), 0); }
  177. While (P <> BlockEnd) Do
  178. Begin
  179. CurProp := New(PPaiProp, init);
  180. If (p <> NewBlockStart)
  181. Then
  182. Begin
  183. {$ifdef JumpAnal}
  184. If (p^.Typ <> ait_label) Then
  185. {$endif JumpAnal}
  186. Begin
  187. GetLastInstruction(p, hp);
  188. CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
  189. CurProp^.CondRegs.Flags :=
  190. PPaiProp(hp^.OptInfo)^.CondRegs.Flags;
  191. End
  192. End;
  193. CurProp^.UsedRegs.InitWithValue(UsedRegs.GetUsedRegs);
  194. { CurProp^.CanBeRemoved := False;}
  195. UsedRegs.Update(Pai(p^.Next)));
  196. PPaiProp(p^.OptInfo) := CurProp;
  197. For TmpReg := R_EAX To R_EDI Do
  198. Inc(NrOfInstrSinceLastMod[TmpReg]);
  199. Case p^.typ Of
  200. ait_label:
  201. {$Ifndef JumpAnal}
  202. If (Pai_label(p)^.l^.is_used) Then
  203. CurProp^.DestroyAllRegs;
  204. {$Else JumpAnal}
  205. Begin
  206. If (Pai_Label(p)^.is_used) Then
  207. With LTable^[Pai_Label(p)^.l^.labelnr-LoLab] Do
  208. {$IfDef AnalyzeLoops}
  209. If (RefsFound = Pai_Label(p)^.l^.RefCount)
  210. {$Else AnalyzeLoops}
  211. If (JmpsProcessed = Pai_Label(p)^.l^.RefCount)
  212. {$EndIf AnalyzeLoops}
  213. Then
  214. {all jumps to this label have been found}
  215. {$IfDef AnalyzeLoops}
  216. If (JmpsProcessed > 0)
  217. Then
  218. {$EndIf AnalyzeLoops}
  219. {we've processed at least one jump to this label}
  220. Begin
  221. If (GetLastInstruction(p, hp) And
  222. Not(((hp^.typ = ait_instruction)) And
  223. (pai386_labeled(hp)^.is_jmp))
  224. Then
  225. {previous instruction not a JMP -> the contents of the registers after the
  226. previous intruction has been executed have to be taken into account as well}
  227. For TmpReg := R_EAX to R_EDI Do
  228. Begin
  229. If (CurProp^.Regs[TmpReg].WState <>
  230. PPaiProp(hp^.OptInfo)^.Regs[TmpReg].WState)
  231. Then DestroyReg(CurProp, TmpReg)
  232. End
  233. End
  234. {$IfDef AnalyzeLoops}
  235. Else
  236. {a label from a backward jump (e.g. a loop), no jump to this label has
  237. already been processed}
  238. If GetLastInstruction(p, hp) And
  239. Not(hp^.typ = ait_instruction) And
  240. (pai386_labeled(hp)^.opcode = A_JMP))
  241. Then
  242. {previous instruction not a jmp, so keep all the registers' contents from the
  243. previous instruction}
  244. Begin
  245. CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
  246. CurProp^.DirFlag := PPaiProp(hp^.OptInfo)^.DirFlag;
  247. End
  248. Else
  249. {previous instruction a jmp and no jump to this label processed yet}
  250. Begin
  251. hp := p;
  252. Cnt := InstrCnt;
  253. {continue until we find a jump to the label or a label which has already
  254. been processed}
  255. While GetNextInstruction(hp, hp) And
  256. Not((hp^.typ = ait_instruction) And
  257. (pai386(hp)^.is_jmp) and
  258. (pasmlabel(pai386(hp)^.oper[0].sym)^.labelnr = Pai_Label(p)^.l^.labelnr)) And
  259. Not((hp^.typ = ait_label) And
  260. (LTable^[Pai_Label(hp)^.l^.labelnr-LoLab].RefsFound
  261. = Pai_Label(hp)^.l^.RefCount) And
  262. (LTable^[Pai_Label(hp)^.l^.labelnr-LoLab].JmpsProcessed > 0)) Do
  263. Inc(Cnt);
  264. If (hp^.typ = ait_label)
  265. Then
  266. {there's a processed label after the current one}
  267. Begin
  268. CurProp^.Regs := PaiPropBlock^[Cnt].Regs;
  269. CurProp^.DirFlag := PaiPropBlock^[Cnt].DirFlag;
  270. End
  271. Else
  272. {there's no label anymore after the current one, or they haven't been
  273. processed yet}
  274. Begin
  275. GetLastInstruction(p, hp);
  276. CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
  277. CurProp^.DirFlag := PPaiProp(hp^.OptInfo)^.DirFlag;
  278. DestroyAllRegs(PPaiProp(hp^.OptInfo))
  279. End
  280. End
  281. {$EndIf AnalyzeLoops}
  282. Else
  283. {not all references to this label have been found, so destroy all registers}
  284. Begin
  285. GetLastInstruction(p, hp);
  286. CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
  287. CurProp^.DirFlag := PPaiProp(hp^.OptInfo)^.DirFlag;
  288. DestroyAllRegs(CurProp)
  289. End;
  290. End;
  291. {$EndIf JumpAnal}
  292. {$ifdef GDB}
  293. ait_stabs, ait_stabn, ait_stab_function_name:;
  294. {$endif GDB}
  295. ait_instruction:
  296. Begin
  297. if pai386(p)^.is_jmp then
  298. begin
  299. {$IfNDef JumpAnal}
  300. ;
  301. {$Else JumpAnal}
  302. With LTable^[pasmlabel(pai386(p)^.oper[0].sym)^.labelnr-LoLab] Do
  303. If (RefsFound = pasmlabel(pai386(p)^.oper[0].sym)^.RefCount) Then
  304. Begin
  305. If (InstrCnt < InstrNr)
  306. Then
  307. {forward jump}
  308. If (JmpsProcessed = 0) Then
  309. {no jump to this label has been processed yet}
  310. Begin
  311. PaiPropBlock^[InstrNr].Regs := CurProp^.Regs;
  312. PaiPropBlock^[InstrNr].DirFlag := CurProp^.DirFlag;
  313. Inc(JmpsProcessed);
  314. End
  315. Else
  316. Begin
  317. For TmpReg := R_EAX to R_EDI Do
  318. If (PaiPropBlock^[InstrNr].Regs[TmpReg].WState <>
  319. CurProp^.Regs[TmpReg].WState) Then
  320. DestroyReg(@PaiPropBlock^[InstrNr], TmpReg);
  321. Inc(JmpsProcessed);
  322. End
  323. {$ifdef AnalyzeLoops}
  324. Else
  325. { backward jump, a loop for example}
  326. { If (JmpsProcessed > 0) Or
  327. Not(GetLastInstruction(PaiObj, hp) And
  328. (hp^.typ = ait_labeled_instruction) And
  329. (pai386_labeled(hp)^.opcode = A_JMP))
  330. Then}
  331. {instruction prior to label is not a jmp, or at least one jump to the label
  332. has yet been processed}
  333. Begin
  334. Inc(JmpsProcessed);
  335. For TmpReg := R_EAX to R_EDI Do
  336. If (PaiPropBlock^[InstrNr].Regs[TmpReg].WState <>
  337. CurProp^.Regs[TmpReg].WState)
  338. Then
  339. Begin
  340. TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
  341. Cnt := InstrNr;
  342. While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
  343. Begin
  344. DestroyReg(@PaiPropBlock^[Cnt], TmpReg);
  345. Inc(Cnt);
  346. End;
  347. While (Cnt <= InstrCnt) Do
  348. Begin
  349. Inc(PaiPropBlock^[Cnt].Regs[TmpReg].WState);
  350. Inc(Cnt)
  351. End
  352. End;
  353. End
  354. { Else }
  355. {instruction prior to label is a jmp and no jumps to the label have yet been
  356. processed}
  357. { Begin
  358. Inc(JmpsProcessed);
  359. For TmpReg := R_EAX to R_EDI Do
  360. Begin
  361. TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
  362. Cnt := InstrNr;
  363. While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
  364. Begin
  365. PaiPropBlock^[Cnt].Regs[TmpReg] := CurProp^.Regs[TmpReg];
  366. Inc(Cnt);
  367. End;
  368. TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
  369. While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
  370. Begin
  371. DestroyReg(@PaiPropBlock^[Cnt], TmpReg);
  372. Inc(Cnt);
  373. End;
  374. While (Cnt <= InstrCnt) Do
  375. Begin
  376. Inc(PaiPropBlock^[Cnt].Regs[TmpReg].WState);
  377. Inc(Cnt)
  378. End
  379. End
  380. End}
  381. {$endif AnalyzeLoops}
  382. End;
  383. {$EndIf JumpAnal}
  384. end
  385. else
  386. begin
  387. InstrProp := AsmInstr[PInstr(p)^.opcode];
  388. If IsStoreInstr(p) Then
  389. Begin
  390. CurProp^.ReadReg(PInstr(p)^.oper[StoreSrc].reg);
  391. CurProp^.ReadRef(PInstr(p)^.oper[StoreDst].ref);
  392. CurProp^.DestroyRefs(PInstr(p)^.oper[StoreDst].ref^,
  393. PInstr(p)^.oper[StoreSrc].reg);
  394. End
  395. Else If IsLoadInstr(p) Then
  396. Begin
  397. CurProp^.ReadRef(PInstr(p)^.oper[LoadSrc].ref);
  398. CurProp^.ReadReg(PInstr(p)^.oper[LoadDst].reg);
  399. TmpReg := RegMaxSize(PInstr(p)^.oper[1].reg);
  400. If RegInRef(TmpReg, Pai386(p)^.oper[0].ref^) And
  401. (CurProp^.Regs[TmpReg].Typ = Con_Ref)
  402. Then
  403. Begin
  404. With CurProp^.Regs[TmpReg] Do
  405. Begin
  406. IncState(WState);
  407. {also store how many instructions are part of the sequence in the first
  408. instructions PPaiProp, so it can be easily accessed from within
  409. CheckSequence}
  410. Inc(NrOfMods, NrOfInstrSinceLastMod[TmpReg]);
  411. PPaiProp(Pai(StartMod)^.OptInfo)^.Regs[TmpReg].NrOfMods := NrOfMods;
  412. NrOfInstrSinceLastMod[TmpReg] := 0;
  413. End;
  414. End
  415. Else
  416. Begin
  417. DestroyReg(CurProp, TmpReg);
  418. If Not(RegInRef(TmpReg, Pai386(p)^.oper[0].ref^)) Then
  419. With CurProp^.Regs[TmpReg] Do
  420. Begin
  421. Typ := Con_Ref;
  422. StartMod := p;
  423. NrOfMods := 1;
  424. End
  425. End;
  426. {$ifdef StateDebug}
  427. hp := new(pai_asm_comment,init(strpnew(att_reg2str[TmpReg]+': '+tostr(CurProp^.Regs[TmpReg].WState))));
  428. InsertLLItem(AsmL, p, p^.next, hp);
  429. {$endif StateDebug}
  430. End;
  431. Top_Const:
  432. Begin
  433. Case Pai386(p)^.oper[1].typ Of
  434. Top_Reg:
  435. Begin
  436. TmpReg := Reg32(Pai386(p)^.oper[1].reg);
  437. With CurProp^.Regs[TmpReg] Do
  438. Begin
  439. DestroyReg(CurProp, TmpReg);
  440. typ := Con_Const;
  441. StartMod := p;
  442. End
  443. End;
  444. Top_Ref:
  445. Begin
  446. ReadRef(CurProp, Pai386(p)^.oper[1].ref);
  447. DestroyRefs(P, Pai386(p)^.oper[1].ref^, R_NO);
  448. End;
  449. End;
  450. End;
  451. End;
  452. End;
  453. A_IMUL:
  454. Begin
  455. ReadOp(CurProp, Pai386(p)^.oper[0]);
  456. ReadOp(CurProp, Pai386(p)^.oper[1]);
  457. If (Pai386(p)^.oper[2].typ = top_none) Then
  458. If (Pai386(p)^.oper[1].typ = top_none) Then
  459. Begin
  460. DestroyReg(CurProp, R_EAX);
  461. DestroyReg(CurProp, R_EDX)
  462. End
  463. Else
  464. {$ifdef arithopt}
  465. AddInstr2OpContents(Pai386(p), Pai386(p)^.oper[1])
  466. {$else arithopt}
  467. DestroyOp(p, Pai386(p)^.oper[1])
  468. {$endif arithopt}
  469. Else
  470. {$ifdef arithopt}
  471. AddInstr2OpContents(Pai386(p), Pai386(p)^.oper[2]);
  472. {$else arithopt}
  473. DestroyOp(p, Pai386(p)^.oper[2]);
  474. {$endif arithopt}
  475. End;
  476. A_XOR:
  477. Begin
  478. ReadOp(CurProp, Pai386(p)^.oper[0]);
  479. ReadOp(CurProp, Pai386(p)^.oper[1]);
  480. If (Pai386(p)^.oper[0].typ = top_reg) And
  481. (Pai386(p)^.oper[1].typ = top_reg) And
  482. (Pai386(p)^.oper[0].reg = Pai386(p)^.oper[1].reg)
  483. Then
  484. Begin
  485. DestroyReg(CurProp, Pai386(p)^.oper[0].reg);
  486. CurProp^.Regs[Reg32(Pai386(p)^.oper[0].reg)].typ := Con_Const;
  487. CurProp^.Regs[Reg32(Pai386(p)^.oper[0].reg)].StartMod := Pointer(0)
  488. End
  489. Else
  490. DestroyOp(p, Pai386(p)^.oper[1]);
  491. End
  492. Else
  493. Begin
  494. Cnt := 1;
  495. While (Cnt <= MaxCh) And
  496. (InstrProp.Ch[Cnt] <> C_None) Do
  497. Begin
  498. Case InstrProp.Ch[Cnt] Of
  499. C_REAX..C_REDI: ReadReg(CurProp,TCh2Reg(InstrProp.Ch[Cnt]));
  500. C_WEAX..C_RWEDI:
  501. Begin
  502. If (InstrProp.Ch[Cnt] >= C_RWEAX) Then
  503. ReadReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]));
  504. DestroyReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]));
  505. End;
  506. {$ifdef arithopt}
  507. C_MEAX..C_MEDI:
  508. AddInstr2RegContents({$ifdef statedebug} asml, {$endif}
  509. Pai386(p),
  510. TCh2Reg(InstrProp.Ch[Cnt]));
  511. {$endif arithopt}
  512. C_CDirFlag: CurProp^.DirFlag := F_NotSet;
  513. C_SDirFlag: CurProp^.DirFlag := F_Set;
  514. C_Rop1: ReadOp(CurProp, Pai386(p)^.oper[0]);
  515. C_Rop2: ReadOp(CurProp, Pai386(p)^.oper[1]);
  516. C_ROp3: ReadOp(CurProp, Pai386(p)^.oper[2]);
  517. C_Wop1..C_RWop1:
  518. Begin
  519. If (InstrProp.Ch[Cnt] in [C_RWop1]) Then
  520. ReadOp(CurProp, Pai386(p)^.oper[0]);
  521. DestroyOp(p, Pai386(p)^.oper[0]);
  522. End;
  523. {$ifdef arithopt}
  524. C_Mop1:
  525. AddInstr2OpContents({$ifdef statedebug} asml, {$endif}
  526. Pai386(p), Pai386(p)^.oper[0]);
  527. {$endif arithopt}
  528. C_Wop2..C_RWop2:
  529. Begin
  530. If (InstrProp.Ch[Cnt] = C_RWop2) Then
  531. ReadOp(CurProp, Pai386(p)^.oper[1]);
  532. DestroyOp(p, Pai386(p)^.oper[1]);
  533. End;
  534. {$ifdef arithopt}
  535. C_Mop2:
  536. AddInstr2OpContents({$ifdef statedebug} asml, {$endif}
  537. Pai386(p), Pai386(p)^.oper[1]);
  538. {$endif arithopt}
  539. C_WOp3..C_RWOp3:
  540. Begin
  541. If (InstrProp.Ch[Cnt] = C_RWOp3) Then
  542. ReadOp(CurProp, Pai386(p)^.oper[2]);
  543. DestroyOp(p, Pai386(p)^.oper[2]);
  544. End;
  545. {$ifdef arithopt}
  546. C_Mop3:
  547. AddInstr2OpContents({$ifdef statedebug} asml, {$endif}
  548. Pai386(p), Pai386(p)^.oper[2]);
  549. {$endif arithopt}
  550. C_WMemEDI:
  551. Begin
  552. ReadReg(CurProp, R_EDI);
  553. FillChar(TmpRef, SizeOf(TmpRef), 0);
  554. TmpRef.Base := R_EDI;
  555. DestroyRefs(p, TmpRef, R_NO)
  556. End;
  557. C_RFlags, C_WFlags, C_RWFlags, C_FPU:
  558. Else
  559. Begin
  560. DestroyAllRegs(CurProp);
  561. End;
  562. End;
  563. Inc(Cnt);
  564. End
  565. End;
  566. end;
  567. End;
  568. End
  569. Else
  570. Begin
  571. DestroyAllRegs(CurProp);
  572. End;
  573. End;
  574. Inc(InstrCnt);
  575. GetNextInstruction(p, p);
  576. End;
  577. End;
  578. End.