idioms.cpp 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359
  1. /*****************************************************************************
  2. * dcc project machine idiom recognition
  3. * (C) Cristina Cifuentes
  4. ****************************************************************************/
  5. #include "dcc.h"
  6. #include <string.h>
  7. #ifdef __DOSWIN__
  8. #include <stdio.h>
  9. #endif
  10. /*****************************************************************************
  11. * JmpInst - Returns TRUE if opcode is a conditional or unconditional jump
  12. ****************************************************************************/
  13. boolT JmpInst(llIcode opcode)
  14. {
  15. switch (opcode) {
  16. case iJMP: case iJMPF: case iJCXZ:
  17. case iLOOP: case iLOOPE:case iLOOPNE:
  18. case iJB: case iJBE: case iJAE: case iJA:
  19. case iJL: case iJLE: case iJGE: case iJG:
  20. case iJE: case iJNE: case iJS: case iJNS:
  21. case iJO: case iJNO: case iJP: case iJNP:
  22. return TRUE;
  23. }
  24. return FALSE;
  25. }
  26. /*****************************************************************************
  27. /* checkStkVars - Checks for PUSH SI
  28. * [PUSH DI]
  29. * or PUSH DI
  30. * [PUSH SI]
  31. * In which case, the stack variable flags are set
  32. ****************************************************************************/
  33. static Int checkStkVars (ICODE * pIcode, ICODE * pEnd, Function * pProc)
  34. {
  35. /* Look for PUSH SI */
  36. if ((pIcode < pEnd) && (pIcode->ic.ll.opcode == iPUSH) &&
  37. (pIcode->ic.ll.dst.regi == rSI))
  38. {
  39. pProc->flg |= SI_REGVAR;
  40. /* Look for PUSH DI */
  41. if (++pIcode < pEnd && (pIcode->ic.ll.opcode == iPUSH) &&
  42. (pIcode->ic.ll.dst.regi == rDI))
  43. {
  44. pProc->flg |= DI_REGVAR;
  45. return 2;
  46. }
  47. else
  48. return 1;
  49. }
  50. else if ((pIcode < pEnd) && (pIcode->ic.ll.opcode == iPUSH) &&
  51. (pIcode->ic.ll.dst.regi == rDI))
  52. {
  53. pProc->flg |= DI_REGVAR;
  54. /* Look for PUSH SI */
  55. if ((++pIcode < pEnd) && (pIcode->ic.ll.opcode == iPUSH) &&
  56. (pIcode->ic.ll.dst.regi == rSI))
  57. {
  58. pProc->flg |= SI_REGVAR;
  59. return 2;
  60. }
  61. else
  62. return 1;
  63. }
  64. return 0;
  65. }
  66. /*****************************************************************************
  67. * idiom1 - HLL procedure prologue; Returns number of instructions matched.
  68. * PUSH BP ==> ENTER immed, 0
  69. * MOV BP, SP and sets PROC_HLL flag
  70. * [SUB SP, immed]
  71. * [PUSH SI]
  72. * [PUSH DI]
  73. * - Second version: Push stack variables and then save BP
  74. * PUSH BP
  75. * PUSH SI
  76. * [PUSH DI]
  77. * MOV BP, SP
  78. * - Third version: Stack variables
  79. * [PUSH SI]
  80. * [PUSH DI]
  81. ****************************************************************************/
  82. static Int idiom1(ICODE * pIcode, ICODE * pEnd, Function * pProc)
  83. { Int n;
  84. /* PUSH BP as first instruction of procedure */
  85. if ( !(pIcode->ic.ll.flg & I) && pIcode->ic.ll.src.regi == rBP)
  86. {
  87. /* MOV BP, SP as next instruction */
  88. if (++pIcode < pEnd && ! (pIcode->ic.ll.flg & (I | TARGET | CASE))
  89. && pIcode->ic.ll.opcode == iMOV && pIcode->ic.ll.dst.regi == rBP
  90. && pIcode->ic.ll.src.regi == rSP)
  91. {
  92. pProc->args.minOff = 2;
  93. pProc->flg |= PROC_IS_HLL;
  94. /* Look for SUB SP, immed */
  95. if ((++pIcode < pEnd) &&
  96. (pIcode->ic.ll.flg & (I | TARGET | CASE)) == I &&
  97. pIcode->ic.ll.opcode == iSUB && pIcode->ic.ll.dst.regi == rSP)
  98. {
  99. return (3 + checkStkVars (++pIcode, pEnd, pProc));
  100. }
  101. else
  102. return (2 + checkStkVars (pIcode, pEnd, pProc));
  103. }
  104. /* PUSH SI
  105. * [PUSH DI]
  106. * MOV BP, SP */
  107. else
  108. {
  109. n = checkStkVars (pIcode, pEnd, pProc);
  110. if (n > 0)
  111. {
  112. /* Look for MOV BP, SP */
  113. pIcode += n;
  114. if (pIcode < pEnd &&
  115. ! (pIcode->ic.ll.flg & (I | TARGET | CASE)) &&
  116. pIcode->ic.ll.opcode == iMOV &&
  117. pIcode->ic.ll.dst.regi == rBP &&
  118. pIcode->ic.ll.src.regi == rSP)
  119. {
  120. pProc->args.minOff = 2 + (n * 2);
  121. return (2 + n);
  122. }
  123. else return 0; // Cristina: check this please!
  124. }
  125. else return 0; // Cristina: check this please!
  126. }
  127. }
  128. else
  129. return (checkStkVars (pIcode, pEnd, pProc));
  130. }
  131. /*****************************************************************************
  132. * popStkVars - checks for
  133. * [POP DI]
  134. * [POP SI]
  135. * or [POP SI]
  136. * [POP DI]
  137. ****************************************************************************/
  138. static void popStkVars (ICODE * pIcode, ICODE * pEnd, Function * pProc)
  139. {
  140. /* Match [POP DI] */
  141. if (pIcode->ic.ll.opcode == iPOP)
  142. if ((pProc->flg & DI_REGVAR) && (pIcode->ic.ll.dst.regi == rDI))
  143. pIcode->invalidate();
  144. else if ((pProc->flg & SI_REGVAR) && (pIcode->ic.ll.dst.regi == rSI))
  145. pIcode->invalidate();
  146. /* Match [POP SI] */
  147. if ((pIcode+1)->ic.ll.opcode == iPOP)
  148. if ((pProc->flg & SI_REGVAR) && ((pIcode+1)->ic.ll.dst.regi == rSI))
  149. (pIcode+1)->invalidate();
  150. else if ((pProc->flg & DI_REGVAR) && ((pIcode+1)->ic.ll.dst.regi == rDI))
  151. (pIcode+1)->invalidate();
  152. }
  153. /*****************************************************************************
  154. * idiom2 - HLL procedure epilogue; Returns number of instructions matched.
  155. * [POP DI]
  156. * [POP SI]
  157. * MOV SP, BP
  158. * POP BP
  159. * RET(F)
  160. *****************************************************************************/
  161. static Int idiom2(ICODE * pIcode, ICODE * pEnd, Int ip, Function * pProc)
  162. { ICODE * nicode;
  163. /* Match MOV SP, BP */
  164. if (ip != 0 && ((pIcode->ic.ll.flg & I) != I) &&
  165. pIcode->ic.ll.dst.regi == rSP && pIcode->ic.ll.src.regi == rBP)
  166. {
  167. /* Get next icode, skip over holes in the icode array */
  168. nicode = pIcode + 1;
  169. while (nicode->ic.ll.flg & NO_CODE)
  170. nicode++;
  171. /* Match POP BP */
  172. if (nicode < pEnd &&
  173. ! (nicode->ic.ll.flg & (I | TARGET | CASE)) &&
  174. nicode->ic.ll.opcode == iPOP &&
  175. nicode->ic.ll.dst.regi == rBP)
  176. {
  177. nicode++;
  178. /* Match RET(F) */
  179. if (nicode < pEnd &&
  180. ! (nicode->ic.ll.flg & (I | TARGET | CASE)) &&
  181. (nicode->ic.ll.opcode == iRET ||
  182. nicode->ic.ll.opcode == iRETF))
  183. {
  184. popStkVars (pIcode-2, pEnd, pProc);
  185. return 2;
  186. }
  187. }
  188. }
  189. return 0;
  190. }
  191. /*****************************************************************************
  192. * idiom3 - C calling convention.
  193. * CALL(F) proc_X
  194. * ADD SP, immed
  195. * Eg: CALL proc_X
  196. * ADD SP, 6
  197. * => pProc->cbParam = immed
  198. * Special case: when the call is at the end of the procedure,
  199. * sometimes the stack gets restored by a MOV sp, bp.
  200. * Need to flag the procedure in these cases.
  201. * Used by compilers to restore the stack when invoking a procedure using
  202. * the C calling convention.
  203. ****************************************************************************/
  204. static Int idiom3(ICODE * pIcode, ICODE * pEnd)
  205. {
  206. /* Match ADD SP, immed */
  207. ++pIcode;
  208. if ((pIcode < pEnd) && (pIcode->ic.ll.flg & I) &&
  209. (pIcode->ic.ll.opcode == iADD) && (pIcode->ic.ll.dst.regi == rSP))
  210. return (pIcode->ic.ll.immed.op);
  211. else if ((pIcode->ic.ll.opcode == iMOV) && (pIcode->ic.ll.dst.regi == rSP)
  212. && (pIcode->ic.ll.src.regi == rBP))
  213. (pIcode-1)->ic.ll.flg |= REST_STK;
  214. return 0;
  215. }
  216. /*****************************************************************************
  217. * idiom 17 - C calling convention.
  218. * CALL(F) xxxx
  219. * POP reg
  220. * [POP reg] reg in {AX, BX, CX, DX}
  221. * Eg: CALL proc_X
  222. * POP cx
  223. * POP cx (4 bytes of arguments)
  224. * => pProc->cbParam = # pops * 2
  225. * Found in Turbo C when restoring the stack for a procedure that uses the
  226. * C calling convention. Used to restore the stack of 2 or 4 bytes args.
  227. ****************************************************************************/
  228. static Int idiom17 (ICODE * pIcode, ICODE * pEnd)
  229. { Int i = 0; /* Count on # pops */
  230. byte regi;
  231. /* Match POP reg */
  232. ++pIcode;
  233. if ((pIcode < pEnd) && (pIcode->ic.ll.opcode == iPOP))
  234. {
  235. regi = pIcode->ic.ll.dst.regi;
  236. if ((regi >= rAX) && (regi <= rBX))
  237. i++;
  238. ++pIcode;
  239. while (pIcode->ic.ll.opcode == iPOP)
  240. {
  241. if (pIcode->ic.ll.dst.regi == regi)
  242. {
  243. i++;
  244. ++pIcode;
  245. }
  246. else
  247. break;
  248. }
  249. return (i * 2);
  250. }
  251. return (0);
  252. }
  253. /*****************************************************************************
  254. * idiom4 - Pascal calling convention.
  255. * RET(F) immed
  256. * ==> pProc->cbParam = immed
  257. * sets CALL_PASCAL flag
  258. * - Second version: check for optional pop of stack vars
  259. * [POP DI]
  260. * [POP SI]
  261. * POP BP
  262. * RET(F) [immed]
  263. * - Third version: pop stack vars
  264. * [POP DI]
  265. * [POP SI]
  266. * RET(F) [immed]
  267. ****************************************************************************/
  268. static void idiom4 (ICODE * pIcode, ICODE * pEnd, Function * pProc)
  269. {
  270. /* Check for [POP DI]
  271. * [POP SI] */
  272. popStkVars (pIcode-3, pEnd, pProc);
  273. /* Check for POP BP */
  274. if (((pIcode-1)->ic.ll.opcode == iPOP) &&
  275. (((pIcode-1)->ic.ll.flg & I) != I) &&
  276. ((pIcode-1)->ic.ll.dst.regi == rBP))
  277. (pIcode-1)->invalidate();
  278. else
  279. popStkVars (pIcode-2, pEnd, pProc);
  280. /* Check for RET(F) immed */
  281. if (pIcode->ic.ll.flg & I)
  282. {
  283. pProc->cbParam = (int16)pIcode->ic.ll.immed.op;
  284. pProc->flg |= CALL_PASCAL;
  285. }
  286. }
  287. /*****************************************************************************
  288. * idiom5 - Long addition.
  289. * ADD reg/stackOff, reg/stackOff
  290. * ADC reg/stackOff, reg/stackOff
  291. * Eg: ADD ax, [bp-4]
  292. * ADC dx, [bp-2]
  293. * => dx:ax = dx:ax + [bp-2]:[bp-4]
  294. * Found in Borland Turbo C code.
  295. * Commonly used idiom for long addition.
  296. ****************************************************************************/
  297. static boolT idiom5 (ICODE * pIcode, ICODE * pEnd)
  298. {
  299. if (pIcode < pEnd)
  300. if ((pIcode+1)->ic.ll.opcode == iADC)
  301. return true;
  302. return false;
  303. }
  304. /*****************************************************************************
  305. * idiom6 - Long substraction.
  306. * SUB reg/stackOff, reg/stackOff
  307. * SBB reg/stackOff, reg/stackOff
  308. * Eg: SUB ax, [bp-4]
  309. * SBB dx, [bp-2]
  310. * => dx:ax = dx:ax - [bp-2]:[bp-4]
  311. * Found in Borland Turbo C code.
  312. * Commonly used idiom for long substraction.
  313. ****************************************************************************/
  314. static boolT idiom6 (ICODE * pIcode, ICODE * pEnd)
  315. {
  316. if (pIcode < pEnd)
  317. if ((pIcode+1)->ic.ll.opcode == iSBB)
  318. return true;
  319. return false;
  320. }
  321. /*****************************************************************************
  322. * idiom7 - Assign zero
  323. * XOR reg/stackOff, reg/stackOff
  324. * Eg: XOR ax, ax
  325. * => ax = 0
  326. * Found in Borland Turbo C and Microsoft C code.
  327. ****************************************************************************/
  328. static boolT idiom7 (ICODE * pIcode)
  329. {
  330. ICODEMEM *dst, *src;
  331. dst = &pIcode->ic.ll.dst;
  332. src = &pIcode->ic.ll.src;
  333. if (dst->regi == 0) /* global variable */
  334. {
  335. if ((dst->segValue == src->segValue) && (dst->off == src->off))
  336. return true;
  337. }
  338. else if (dst->regi < INDEXBASE) /* register */
  339. {
  340. if (dst->regi == src->regi)
  341. return true;
  342. }
  343. else if ((dst->off) && (dst->seg == rSS) && (dst->regi == INDEXBASE + 6))
  344. /* offset from BP */
  345. {
  346. if ((dst->off == src->off) && (dst->seg == src->seg) &&
  347. (dst->regi == src->regi))
  348. return true;
  349. }
  350. return false;
  351. }
  352. /*****************************************************************************
  353. * idiom21 - Assign long kte with high part zero
  354. * XOR regH, regH
  355. * MOV regL, kte
  356. * => regH:regL = kte
  357. * Eg: XOR dx, dx
  358. * MOV ax, 3
  359. * => dx:ax = 3
  360. * Note: only the following valid combinations are available:
  361. * dx:ax
  362. * cx:bx
  363. * Found in Borland Turbo C code.
  364. ****************************************************************************/
  365. static boolT idiom21 (ICODE * picode, ICODE * pend)
  366. { ICODEMEM *dst, *src;
  367. dst = &picode->ic.ll.dst;
  368. src = &picode->ic.ll.src;
  369. if (((picode+1) < pend) && ((picode+1)->ic.ll.flg & I))
  370. {
  371. if ((dst->regi == src->regi) && (dst->regi > 0) &&
  372. (dst->regi < INDEXBASE))
  373. {
  374. if ((dst->regi == rDX) && ((picode+1)->ic.ll.dst.regi == rAX))
  375. return true;
  376. if ((dst->regi == rCX) && ((picode+1)->ic.ll.dst.regi == rBX))
  377. return true;
  378. }
  379. }
  380. return false;
  381. }
  382. /*****************************************************************************
  383. * idiom8 - Shift right by 1 (signed long ops)
  384. * SAR reg, 1
  385. * RCR reg, 1
  386. * Eg: SAR dx, 1
  387. * RCR ax, 1
  388. * => dx:ax = dx:ax >> 1 (dx:ax are signed long)
  389. * Found in Microsoft C code for long signed variable shift right.
  390. ****************************************************************************/
  391. static boolT idiom8 (ICODE * pIcode, ICODE * pEnd)
  392. {
  393. if (pIcode < pEnd)
  394. {
  395. if (((pIcode->ic.ll.flg & I) == I) && (pIcode->ic.ll.immed.op == 1))
  396. if (((pIcode+1)->ic.ll.opcode == iRCR) &&
  397. (((pIcode+1)->ic.ll.flg & I) == I) &&
  398. ((pIcode+1)->ic.ll.immed.op == 1))
  399. return true;
  400. }
  401. return false;
  402. }
  403. /*****************************************************************************
  404. * idiom 15 - Shift left by n
  405. * SHL reg, 1
  406. * SHL reg, 1
  407. * [...]
  408. * [SHL reg, 1]
  409. * Eg: SHL ax, 1
  410. * SHL ax, 1
  411. * => ax = ax << 2
  412. * Found in Borland Turbo C code to index an array (array multiplication)
  413. ****************************************************************************/
  414. static Int idiom15 (ICODE * picode, ICODE * pend)
  415. { Int n = 1;
  416. byte regi;
  417. if (picode < pend)
  418. {
  419. /* Match SHL reg, 1 */
  420. if ((picode->ic.ll.flg & I) && (picode->ic.ll.immed.op == 1))
  421. {
  422. regi = picode->ic.ll.dst.regi;
  423. while (1)
  424. {
  425. if (((picode+n) < pend) &&
  426. ((picode+n)->ic.ll.opcode == iSHL) &&
  427. ((picode+n)->ic.ll.flg & I) &&
  428. ((picode+n)->ic.ll.immed.op == 1) &&
  429. ((picode+n)->ic.ll.dst.regi == regi))
  430. n++;
  431. else
  432. break;
  433. }
  434. }
  435. }
  436. if (n > 1)
  437. return (n);
  438. else
  439. return (0);
  440. }
  441. /*****************************************************************************
  442. * idiom12 - Shift left long by 1
  443. * SHL reg, 1
  444. * RCL reg, 1
  445. * Eg: SHL ax, 1
  446. * RCL dx, 1
  447. * => dx:ax = dx:ax << 1
  448. * Found in Borland Turbo C code for long variable shift left.
  449. ****************************************************************************/
  450. static boolT idiom12 (ICODE * pIcode, ICODE * pEnd)
  451. {
  452. if (pIcode < pEnd)
  453. {
  454. if (((pIcode->ic.ll.flg & I) == I) && (pIcode->ic.ll.immed.op == 1))
  455. if (((pIcode+1)->ic.ll.opcode == iRCL) &&
  456. (((pIcode+1)->ic.ll.flg & I) == I) &&
  457. ((pIcode+1)->ic.ll.immed.op == 1))
  458. return true;
  459. }
  460. return false;
  461. }
  462. /*****************************************************************************
  463. * idiom9 - Shift right by 1 (unsigned long ops)
  464. * SHR reg, 1
  465. * RCR reg, 1
  466. * Eg: SHR dx, 1
  467. * RCR ax, 1
  468. * => dx:ax = dx:ax >> 1 (dx:ax are unsigned long)
  469. * Found in Microsoft C code for long unsigned variable shift right.
  470. ****************************************************************************/
  471. static boolT idiom9 (ICODE * pIcode, ICODE * pEnd)
  472. {
  473. if (pIcode < pEnd)
  474. {
  475. if (((pIcode->ic.ll.flg & I) == I) && (pIcode->ic.ll.immed.op == 1))
  476. if (((pIcode+1)->ic.ll.opcode == iRCR) &&
  477. (((pIcode+1)->ic.ll.flg & I) == I) &&
  478. ((pIcode+1)->ic.ll.immed.op == 1))
  479. return true;
  480. }
  481. return false;
  482. }
  483. /*****************************************************************************
  484. * idiom10 - Jump if not equal to 0
  485. * OR reg, reg
  486. * JNE labX
  487. * Eg: OR ax, ax
  488. * JNE labX
  489. * => HLI_JCOND (ax != 0) labX
  490. * Note: we also check that these instructions are not followed by
  491. * CMP reg, kte
  492. * JE lab
  493. * because this is most likely a long conditional equality test.
  494. * Found in Borland Turbo C.
  495. ****************************************************************************/
  496. static boolT idiom10old (ICODE * pIcode, ICODE * pEnd)
  497. {
  498. if (pIcode < pEnd)
  499. {
  500. /* Check OR reg, reg */
  501. if (((pIcode->ic.ll.flg & I) != I) &&
  502. (pIcode->ic.ll.src. regi > 0) &&
  503. (pIcode->ic.ll.src.regi < INDEXBASE) &&
  504. (pIcode->ic.ll.src.regi == pIcode->ic.ll.dst.regi))
  505. if ((pIcode+3) < pEnd)
  506. {
  507. if (((pIcode+1)->ic.ll.opcode == iJNE) &&
  508. ((pIcode+2)->ic.ll.opcode != iCMP) &&
  509. ((pIcode+3)->ic.ll.opcode != iJE))
  510. return true;
  511. }
  512. else /* at the end of the procedure */
  513. if (((pIcode+1) < pEnd) && ((pIcode+1)->ic.ll.opcode == iJNE))
  514. return true;
  515. }
  516. return false;
  517. }
  518. /*****************************************************************************
  519. * idiom10 - Jump if not equal to 0
  520. * OR reg, reg
  521. * JNE labX
  522. * Eg: OR ax, ax
  523. * JNE labX
  524. * => CMP reg 0
  525. * JNE labX
  526. * This instruction is NOT converted into the equivalent high-level
  527. * instruction "HLI_JCOND (reg != 0) labX" because we do not know yet if
  528. * it forms part of a long register conditional test. It is therefore
  529. * modified to simplify the analysis.
  530. * Found in Borland Turbo C.
  531. ****************************************************************************/
  532. static void idiom10 (ICODE * pIcode, ICODE * pEnd)
  533. {
  534. if (pIcode < pEnd)
  535. {
  536. /* Check OR reg, reg */
  537. if (((pIcode->ic.ll.flg & I) != I) &&
  538. (pIcode->ic.ll.src. regi > 0) &&
  539. (pIcode->ic.ll.src.regi < INDEXBASE) &&
  540. (pIcode->ic.ll.src.regi == pIcode->ic.ll.dst.regi))
  541. if (((pIcode+1) < pEnd) && ((pIcode+1)->ic.ll.opcode == iJNE))
  542. {
  543. pIcode->ic.ll.opcode = iCMP;
  544. pIcode->ic.ll.flg |= I;
  545. pIcode->ic.ll.immed.op = 0;
  546. pIcode->du.def = 0;
  547. pIcode->du1.numRegsDef = 0;
  548. }
  549. }
  550. }
  551. /*****************************************************************************
  552. * idiom 13 - Word assign
  553. * MOV regL, mem
  554. * MOV regH, 0
  555. * Eg: MOV al, [bp-2]
  556. * MOV ah, 0
  557. * => MOV ax, [bp-2]
  558. * Found in Borland Turbo C, used for multiplication and division of
  559. * byte operands (ie. they need to be extended to words).
  560. ****************************************************************************/
  561. static byte idiom13 (ICODE * picode, ICODE * pend)
  562. { byte regi;
  563. if (picode < pend)
  564. {
  565. /* Check for regL */
  566. regi = picode->ic.ll.dst.regi;
  567. if (((picode->ic.ll.flg & I) != I) && (regi >= rAL) && (regi <= rBH))
  568. {
  569. /* Check for MOV regH, 0 */
  570. if (((picode+1)->ic.ll.opcode == iMOV) &&
  571. ((picode+1)->ic.ll.flg & I) &&
  572. ((picode+1)->ic.ll.immed.op == 0))
  573. {
  574. if ((picode+1)->ic.ll.dst.regi == (regi + 4))
  575. return (regi - rAL + rAX);
  576. }
  577. }
  578. }
  579. return (0);
  580. }
  581. /*****************************************************************************
  582. * idiom 14 - Long word assign
  583. * MOV regL, mem/reg
  584. * XOR regH, regH
  585. * Eg: MOV ax, di
  586. * XOR dx, dx
  587. * => MOV dx:ax, di
  588. * Note: only the following combinations are allowed:
  589. * dx:ax
  590. * cx:bx
  591. * this is to remove the possibility of making errors in situations
  592. * like this:
  593. * MOV dx, offH
  594. * MOV ax, offL
  595. * XOR cx, cx
  596. * Found in Borland Turbo C, used for division of unsigned integer
  597. * operands.
  598. ****************************************************************************/
  599. static boolT idiom14 (ICODE * picode, ICODE * pend, byte *regL, byte *regH)
  600. {
  601. if (picode < pend)
  602. {
  603. /* Check for regL */
  604. *regL = picode->ic.ll.dst.regi;
  605. if (((picode->ic.ll.flg & I) != I) && ((*regL == rAX) || (*regL ==rBX)))
  606. {
  607. /* Check for XOR regH, regH */
  608. if (((picode+1)->ic.ll.opcode == iXOR) &&
  609. (((picode+1)->ic.ll.flg & I) != I))
  610. {
  611. *regH = (picode+1)->ic.ll.dst.regi;
  612. if (*regH == (picode+1)->ic.ll.src.regi)
  613. {
  614. if ((*regL == rAX) && (*regH == rDX))
  615. return true;
  616. if ((*regL == rBX) && (*regH == rCX))
  617. return true;
  618. }
  619. }
  620. }
  621. }
  622. return false;
  623. }
  624. /*****************************************************************************
  625. * idiom11 - Negate long integer
  626. * NEG regH
  627. * NEG regL
  628. * SBB regH, 0
  629. * Eg: NEG dx
  630. * NEG ax
  631. * SBB dx, 0
  632. * => dx:ax = - dx:ax
  633. * Found in Borland Turbo C.
  634. ****************************************************************************/
  635. static boolT idiom11 (ICODE * pIcode, ICODE * pEnd)
  636. { condId type; /* type of argument */
  637. if ((pIcode + 2) < pEnd)
  638. {
  639. type = pIcode->idType(DST);
  640. if ((type != CONSTANT) && (type != OTHER))
  641. {
  642. /* Check NEG reg/mem
  643. * SBB reg/mem, 0*/
  644. if (((pIcode+1)->ic.ll.opcode == iNEG) &&
  645. ((pIcode+2)->ic.ll.opcode == iSBB))
  646. switch (type) {
  647. case GLOB_VAR: if (((pIcode+2)->ic.ll.dst.segValue ==
  648. pIcode->ic.ll.dst.segValue) &&
  649. ((pIcode+2)->ic.ll.dst.off ==
  650. pIcode->ic.ll.dst.off))
  651. return true;
  652. break;
  653. case REGISTER: if ((pIcode+2)->ic.ll.dst.regi ==
  654. pIcode->ic.ll.dst.regi)
  655. return true;
  656. break;
  657. case PARAM:
  658. case LOCAL_VAR: if ((pIcode+2)->ic.ll.dst.off ==
  659. pIcode->ic.ll.dst.off)
  660. return true;
  661. break;
  662. }
  663. }
  664. }
  665. return false;
  666. }
  667. /*****************************************************************************
  668. * idiom 16: Bitwise negation
  669. * NEG reg
  670. * SBB reg, reg
  671. * INC reg
  672. * => ASGN reg, !reg
  673. * Eg: NEG ax
  674. * SBB ax, ax
  675. * INC ax
  676. * => ax = !ax
  677. * Found in Borland Turbo C when negating bitwise.
  678. ****************************************************************************/
  679. static boolT idiom16 (ICODE * picode, ICODE * pend)
  680. { byte regi;
  681. if ((picode+2) < pend)
  682. {
  683. regi = picode->ic.ll.dst.regi;
  684. if ((regi >= rAX) && (regi < INDEXBASE))
  685. {
  686. if (((picode+1)->ic.ll.opcode == iSBB) &&
  687. ((picode+2)->ic.ll.opcode == iINC))
  688. if (((picode+1)->ic.ll.dst.regi ==
  689. ((picode+1)->ic.ll.src.regi)) &&
  690. ((picode+1)->ic.ll.dst.regi == regi) &&
  691. ((picode+2)->ic.ll.dst.regi == regi))
  692. return true;
  693. }
  694. }
  695. return false;
  696. }
  697. /*****************************************************************************
  698. * idiom 18: Post-increment or post-decrement in a conditional jump
  699. * MOV reg, var (including register variables)
  700. * INC var or DEC var
  701. * CMP var, Y
  702. * JX label
  703. * => HLI_JCOND (var++ X Y)
  704. * Eg: MOV ax, si
  705. * INC si
  706. * CMP ax, 8
  707. * JL labX
  708. * => HLI_JCOND (si++ < 8)
  709. * Found in Borland Turbo C. Intrinsic to C languages.
  710. ****************************************************************************/
  711. static boolT idiom18 (ICODE * picode, ICODE * pend, Function * pproc)
  712. { boolT type = 0; /* type of variable: 1 = reg-var, 2 = local */
  713. byte regi; /* register of the MOV */
  714. /* Get variable */
  715. if (picode->ic.ll.dst.regi == 0) /* global variable */
  716. /* not supported yet */ ;
  717. else if (picode->ic.ll.dst.regi < INDEXBASE) /* register */
  718. {
  719. if ((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR))
  720. type = 1;
  721. else if ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR))
  722. type = 1;
  723. }
  724. else if (picode->ic.ll.dst.off) /* local variable */
  725. type = 2;
  726. else /* indexed */
  727. /* not supported yet */ ;
  728. /* Check previous instruction for a MOV */
  729. if (type == 1) /* register variable */
  730. {
  731. if (((picode-1)->ic.ll.opcode == iMOV) &&
  732. ((picode-1)->ic.ll.src.regi == picode->ic.ll.dst.regi))
  733. {
  734. regi = (picode-1)->ic.ll.dst.regi;
  735. if ((regi > 0) && (regi < INDEXBASE))
  736. {
  737. if ((picode < pend) && ((picode+1) < pend) &&
  738. ((picode+1)->ic.ll.opcode == iCMP) &&
  739. ((picode+1)->ic.ll.dst.regi == regi) &&
  740. (((picode+2)->ic.ll.opcode >= iJB) &&
  741. ((picode+2)->ic.ll.opcode < iJCXZ)))
  742. return true;
  743. }
  744. }
  745. }
  746. else if (type == 2) /* local */
  747. {
  748. if (((picode-1)->ic.ll.opcode == iMOV) &&
  749. ((picode-1)->ic.ll.src.off == picode->ic.ll.dst.off))
  750. {
  751. regi = (picode-1)->ic.ll.dst.regi;
  752. if ((regi > 0) && (regi < INDEXBASE))
  753. {
  754. if ((picode < pend) && ((picode+1) < pend) &&
  755. ((picode+1)->ic.ll.opcode == iCMP) &&
  756. ((picode+1)->ic.ll.dst.regi == regi) &&
  757. (((picode+2)->ic.ll.opcode >= iJB) &&
  758. ((picode+2)->ic.ll.opcode < iJCXZ)))
  759. return true;
  760. }
  761. }
  762. }
  763. return false;
  764. }
  765. /*****************************************************************************
  766. * idiom 19: pre-increment or pre-decrement in conditional jump, comparing
  767. * against 0.
  768. * INC var or DEC var (including register vars)
  769. * JX lab JX lab
  770. * => HLI_JCOND (++var X 0) or HLI_JCOND (--var X 0)
  771. * Eg: INC [bp+4]
  772. * JG lab2
  773. * => HLI_JCOND (++[bp+4] > 0)
  774. * Found in Borland Turbo C. Intrinsic to C language.
  775. ****************************************************************************/
  776. static boolT idiom19 (ICODE * picode, ICODE * pend, Function * pproc)
  777. {
  778. if (picode->ic.ll.dst.regi == 0) /* global variable */
  779. /* not supported yet */ ;
  780. else if (picode->ic.ll.dst.regi < INDEXBASE) /* register */
  781. {
  782. if (((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR)) ||
  783. ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR)))
  784. if ((picode < pend) && ((picode+1)->ic.ll.opcode >= iJB) &&
  785. ((picode+1)->ic.ll.opcode < iJCXZ))
  786. return true;
  787. }
  788. else if (picode->ic.ll.dst.off) /* stack variable */
  789. {
  790. if ((picode < pend) && ((picode+1)->ic.ll.opcode >= iJB) &&
  791. ((picode+1)->ic.ll.opcode < iJCXZ))
  792. return true;
  793. }
  794. else /* indexed */
  795. /* not supported yet */ ;
  796. return false;
  797. }
  798. /*****************************************************************************
  799. * idiom20: Pre increment/decrement in conditional expression (compares
  800. * against a register, variable or constant different than 0).
  801. * INC var or DEC var (including register vars)
  802. * MOV reg, var MOV reg, var
  803. * CMP reg, Y CMP reg, Y
  804. * JX lab JX lab
  805. * => HLI_JCOND (++var X Y) or HLI_JCOND (--var X Y)
  806. * Eg: INC si (si is a register variable)
  807. * MOV ax, si
  808. * CMP ax, 2
  809. * JL lab4
  810. * => HLI_JCOND (++si < 2)
  811. * Found in Turbo C. Intrinsic to C language.
  812. ****************************************************************************/
  813. static boolT idiom20 (ICODE * picode, ICODE * pend, Function * pproc)
  814. { boolT type = 0; /* type of variable: 1 = reg-var, 2 = local */
  815. byte regi; /* register of the MOV */
  816. /* Get variable */
  817. if (picode->ic.ll.dst.regi == 0) /* global variable */
  818. /* not supported yet */ ;
  819. else if (picode->ic.ll.dst.regi < INDEXBASE) /* register */
  820. {
  821. if ((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR))
  822. type = 1;
  823. else if ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR))
  824. type = 1;
  825. }
  826. else if (picode->ic.ll.dst.off) /* local variable */
  827. type = 2;
  828. else /* indexed */
  829. /* not supported yet */ ;
  830. /* Check previous instruction for a MOV */
  831. if (type == 1) /* register variable */
  832. {
  833. if ((picode < pend) && ((picode+1)->ic.ll.opcode == iMOV) &&
  834. ((picode+1)->ic.ll.src.regi == picode->ic.ll.dst.regi))
  835. {
  836. regi = (picode+1)->ic.ll.dst.regi;
  837. if ((regi > 0) && (regi < INDEXBASE))
  838. {
  839. if (((picode+1) < pend) && ((picode+2) < pend) &&
  840. ((picode+2)->ic.ll.opcode == iCMP) &&
  841. ((picode+2)->ic.ll.dst.regi == regi) &&
  842. (((picode+3)->ic.ll.opcode >= iJB) &&
  843. ((picode+3)->ic.ll.opcode < iJCXZ)))
  844. return true;
  845. }
  846. }
  847. }
  848. else if (type == 2) /* local */
  849. {
  850. if ((picode < pend) && ((picode+1)->ic.ll.opcode == iMOV) &&
  851. ((picode+1)->ic.ll.src.off == picode->ic.ll.dst.off))
  852. {
  853. regi = (picode+1)->ic.ll.dst.regi;
  854. if ((regi > 0) && (regi < INDEXBASE))
  855. {
  856. if (((picode+1) < pend) && ((picode+2) < pend) &&
  857. ((picode+2)->ic.ll.opcode == iCMP) &&
  858. ((picode+2)->ic.ll.dst.regi == regi) &&
  859. (((picode+3)->ic.ll.opcode >= iJB) &&
  860. ((picode+3)->ic.ll.opcode < iJCXZ)))
  861. return true;
  862. }
  863. }
  864. }
  865. return false;
  866. }
  867. /*****************************************************************************
  868. * findIdioms - translates LOW_LEVEL icode idioms into HIGH_LEVEL icodes.
  869. ****************************************************************************/
  870. void Function::findIdioms()
  871. {
  872. Int ip; /* Index to current icode */
  873. ICODE * pEnd, * pIcode; /* Pointers to end of BB and current icodes */
  874. int16 delta;
  875. COND_EXPR *rhs, *lhs; /* Pointers to left and right hand side exps */
  876. COND_EXPR *exp; /* Pointer to temporal expression */
  877. Int idx; /* Index into local identifier table */
  878. byte regH, regL; /* High and low registers for long word reg */
  879. pIcode = &Icode.front();
  880. pEnd = pIcode + Icode.GetNumIcodes();
  881. ip = 0;
  882. while (pIcode < pEnd)
  883. {
  884. switch (pIcode->ic.ll.opcode) {
  885. case iDEC: case iINC:
  886. if (idiom18 (pIcode, pEnd, this))
  887. {
  888. lhs = COND_EXPR::id (pIcode-1, SRC, this, ip, pIcode, eUSE);
  889. if (pIcode->ic.ll.opcode == iDEC)
  890. lhs = COND_EXPR::unary (POST_DEC, lhs);
  891. else
  892. lhs = COND_EXPR::unary (POST_INC, lhs);
  893. rhs = COND_EXPR::id (pIcode+1, SRC, this, ip, pIcode+2, eUSE);
  894. exp = COND_EXPR::boolOp (lhs, rhs,
  895. condOpJCond[(pIcode+2)->ic.ll.opcode - iJB]);
  896. (pIcode+2)->setJCond(exp);
  897. (pIcode-1)->invalidate();
  898. pIcode->invalidate();
  899. (pIcode+1)->invalidate();
  900. pIcode += 3;
  901. ip += 2;
  902. }
  903. else if (idiom19 (pIcode, pEnd, this))
  904. {
  905. lhs = COND_EXPR::id (pIcode, DST, this, ip, pIcode+1, eUSE);
  906. if (pIcode->ic.ll.opcode == iDEC)
  907. lhs = COND_EXPR::unary (PRE_DEC, lhs);
  908. else
  909. lhs = COND_EXPR::unary (PRE_INC, lhs);
  910. rhs = COND_EXPR::idKte (0, 2);
  911. exp = COND_EXPR::boolOp (lhs, rhs,
  912. condOpJCond[(pIcode+1)->ic.ll.opcode - iJB]);
  913. (pIcode+1)->setJCond(exp);
  914. pIcode->invalidate();
  915. pIcode += 2;
  916. ip++;
  917. }
  918. else if (idiom20 (pIcode, pEnd, this))
  919. {
  920. lhs = COND_EXPR::id (pIcode+1, SRC, this, ip, pIcode, eUSE);
  921. if (pIcode->ic.ll.opcode == iDEC)
  922. lhs = COND_EXPR::unary (PRE_DEC, lhs);
  923. else
  924. lhs = COND_EXPR::unary (PRE_INC, lhs);
  925. rhs = COND_EXPR::id (pIcode+2, SRC, this, ip, pIcode+3, eUSE);
  926. exp = COND_EXPR::boolOp (lhs, rhs,
  927. condOpJCond[(pIcode+3)->ic.ll.opcode - iJB]);
  928. (pIcode+3)->setJCond(exp);
  929. pIcode->invalidate();
  930. (pIcode+1)->invalidate();
  931. (pIcode+2)->invalidate();
  932. pIcode += 3;
  933. ip += 2;
  934. }
  935. else
  936. pIcode++;
  937. break;
  938. case iPUSH: /* Idiom 1 */
  939. if ((! (flg & PROC_HLL)) && (idx = idiom1 (pIcode, pEnd, this)))
  940. {
  941. flg |= PROC_HLL;
  942. for ( ; idx > 0; idx--)
  943. {
  944. (pIcode++)->invalidate();
  945. ip++;
  946. }
  947. ip--;
  948. }
  949. else
  950. pIcode++;
  951. break;
  952. case iMOV: /* Idiom 2 */
  953. if (idx = idiom2(pIcode, pEnd, ip, this))
  954. {
  955. pIcode->invalidate();
  956. (pIcode+1)->invalidate();
  957. pIcode += 3;
  958. ip += 2;
  959. }
  960. else if (idiom14 (pIcode, pEnd, &regL, &regH)) /* Idiom 14 */
  961. {
  962. idx = localId.newLongReg (TYPE_LONG_SIGN, regH, regL, ip);
  963. lhs = COND_EXPR::idLongIdx (idx);
  964. pIcode->setRegDU( regH, eDEF);
  965. rhs = COND_EXPR::id (pIcode, SRC, this, ip, pIcode, NONE);
  966. pIcode->setAsgn(lhs, rhs);
  967. (pIcode+1)->invalidate();
  968. pIcode += 2;
  969. ip++;
  970. }
  971. else if (idx = idiom13 (pIcode, pEnd)) /* Idiom 13 */
  972. {
  973. lhs = COND_EXPR::idReg (idx, 0, &localId);
  974. pIcode->setRegDU( idx, eDEF);
  975. pIcode->du1.numRegsDef--; /* prev byte reg def */
  976. rhs = COND_EXPR::id (pIcode, SRC, this, ip, pIcode, NONE);
  977. pIcode->setAsgn(lhs, rhs);
  978. (pIcode+1)->invalidate();
  979. pIcode += 2;
  980. ip++;
  981. }
  982. else
  983. pIcode++;
  984. break;
  985. case iCALL: case iCALLF:
  986. /* Check for library functions that return a long register.
  987. * Propagate this result */
  988. if (pIcode->ic.ll.immed.proc.proc != 0)
  989. if ((pIcode->ic.ll.immed.proc.proc->flg & PROC_ISLIB) &&
  990. (pIcode->ic.ll.immed.proc.proc->flg & PROC_IS_FUNC))
  991. {
  992. if ((pIcode->ic.ll.immed.proc.proc->retVal.type==TYPE_LONG_SIGN)
  993. || (pIcode->ic.ll.immed.proc.proc->retVal.type ==
  994. TYPE_LONG_UNSIGN))
  995. localId.newLongReg(TYPE_LONG_SIGN, rDX, rAX, ip);
  996. }
  997. /* Check for idioms */
  998. if (idx = idiom3(pIcode, pEnd)) /* idiom 3 */
  999. {
  1000. if (pIcode->ic.ll.flg & I)
  1001. {
  1002. (pIcode->ic.ll.immed.proc.proc)->cbParam = (int16)idx;
  1003. pIcode->ic.ll.immed.proc.cb = idx;
  1004. (pIcode->ic.ll.immed.proc.proc)->flg |= CALL_C;
  1005. pIcode++;
  1006. (pIcode++)->invalidate();
  1007. ip++;
  1008. }
  1009. else
  1010. {
  1011. printf("Indirect call at idiom3\n");
  1012. pIcode++;
  1013. }
  1014. }
  1015. else if (idx = idiom17 (pIcode, pEnd)) /* idiom 17 */
  1016. {
  1017. if (pIcode->isLlFlag(I))
  1018. {
  1019. (pIcode->ic.ll.immed.proc.proc)->cbParam = (int16)idx;
  1020. pIcode->ic.ll.immed.proc.cb = idx;
  1021. (pIcode->ic.ll.immed.proc.proc)->flg |= CALL_C;
  1022. ip += idx/2 - 1;
  1023. pIcode++;
  1024. for (idx /= 2; idx > 0; idx--)
  1025. (pIcode++)->invalidate();
  1026. }
  1027. // TODO : it's a calculated call
  1028. else
  1029. {
  1030. printf("Indirect call at idiom17\n");
  1031. pIcode++;
  1032. }
  1033. }
  1034. else
  1035. pIcode++;
  1036. break;
  1037. case iRET: /* Idiom 4 */
  1038. case iRETF:
  1039. idiom4 (pIcode, pEnd, this);
  1040. pIcode++;
  1041. break;
  1042. case iADD: /* Idiom 5 */
  1043. if (idiom5 (pIcode, pEnd))
  1044. {
  1045. lhs = COND_EXPR::idLong (&localId, DST, pIcode, LOW_FIRST,
  1046. ip, USE_DEF, 1);
  1047. rhs = COND_EXPR::idLong (&localId, SRC, pIcode, LOW_FIRST,
  1048. ip, eUSE, 1);
  1049. exp = COND_EXPR::boolOp (lhs, rhs, ADD);
  1050. pIcode->setAsgn(lhs, exp);
  1051. (pIcode+1)->invalidate();
  1052. pIcode++;
  1053. ip++;
  1054. }
  1055. pIcode++;
  1056. break;
  1057. case iSAR: /* Idiom 8 */
  1058. if (idiom8 (pIcode, pEnd))
  1059. {
  1060. idx = localId.newLongReg(TYPE_LONG_SIGN,
  1061. pIcode->ic.ll.dst.regi, (pIcode+1)->ic.ll.dst.regi,ip);
  1062. lhs = COND_EXPR::idLongIdx (idx);
  1063. pIcode->setRegDU( (pIcode+1)->ic.ll.dst.regi, USE_DEF);
  1064. rhs = COND_EXPR::idKte (1, 2);
  1065. exp = COND_EXPR::boolOp (lhs, rhs, SHR);
  1066. pIcode->setAsgn(lhs, exp);
  1067. (pIcode+1)->invalidate();
  1068. pIcode++;
  1069. ip++;
  1070. }
  1071. pIcode++;
  1072. break;
  1073. case iSHL:
  1074. if (idx = idiom15 (pIcode, pEnd)) /* idiom 15 */
  1075. {
  1076. lhs = COND_EXPR::idReg (pIcode->ic.ll.dst.regi,
  1077. pIcode->ic.ll.flg & NO_SRC_B,
  1078. &localId);
  1079. rhs = COND_EXPR::idKte (idx, 2);
  1080. exp = COND_EXPR::boolOp (lhs, rhs, SHL);
  1081. pIcode->setAsgn(lhs, exp);
  1082. pIcode++;
  1083. for (idx-- ; idx > 0; idx--)
  1084. {
  1085. (pIcode++)->invalidate();
  1086. ip++;
  1087. }
  1088. }
  1089. else if (idiom12 (pIcode, pEnd)) /* idiom 12 */
  1090. {
  1091. idx = localId.newLongReg (TYPE_LONG_UNSIGN,
  1092. (pIcode+1)->ic.ll.dst.regi, pIcode->ic.ll.dst.regi,ip);
  1093. lhs = COND_EXPR::idLongIdx (idx);
  1094. pIcode->setRegDU( (pIcode+1)->ic.ll.dst.regi, USE_DEF);
  1095. rhs = COND_EXPR::idKte (1, 2);
  1096. exp = COND_EXPR::boolOp (lhs, rhs, SHL);
  1097. pIcode->setAsgn(lhs, exp);
  1098. (pIcode+1)->invalidate();
  1099. pIcode += 2;
  1100. ip++;
  1101. }
  1102. else
  1103. pIcode++;
  1104. break;
  1105. case iSHR: /* Idiom 9 */
  1106. if (idiom9 (pIcode, pEnd))
  1107. {
  1108. idx = localId.newLongReg (TYPE_LONG_UNSIGN,
  1109. pIcode->ic.ll.dst.regi, (pIcode+1)->ic.ll.dst.regi,ip);
  1110. lhs = COND_EXPR::idLongIdx (idx);
  1111. pIcode->setRegDU( (pIcode+1)->ic.ll.dst.regi, USE_DEF);
  1112. rhs = COND_EXPR::idKte (1, 2);
  1113. exp = COND_EXPR::boolOp (lhs, rhs, SHR);
  1114. pIcode->setAsgn(lhs, exp);
  1115. (pIcode+1)->invalidate();
  1116. pIcode++;
  1117. ip++;
  1118. }
  1119. pIcode++;
  1120. break;
  1121. case iSUB: /* Idiom 6 */
  1122. if (idiom6 (pIcode, pEnd))
  1123. {
  1124. lhs = COND_EXPR::idLong (&localId, DST, pIcode, LOW_FIRST, ip, USE_DEF, 1);
  1125. rhs = COND_EXPR::idLong (&localId, SRC, pIcode, LOW_FIRST, ip, eUSE, 1);
  1126. exp = COND_EXPR::boolOp (lhs, rhs, SUB);
  1127. pIcode->setAsgn(lhs, exp);
  1128. (pIcode+1)->invalidate();
  1129. pIcode++;
  1130. ip++;
  1131. }
  1132. pIcode++;
  1133. break;
  1134. case iOR: /* Idiom 10 */
  1135. idiom10 (pIcode, pEnd);
  1136. pIcode++;
  1137. break;
  1138. case iNEG: /* Idiom 11 */
  1139. if (idiom11 (pIcode, pEnd))
  1140. {
  1141. lhs = COND_EXPR::idLong (&localId, DST, pIcode, HIGH_FIRST,
  1142. ip, USE_DEF, 1);
  1143. rhs = COND_EXPR::unary (NEGATION, lhs);
  1144. pIcode->setAsgn(lhs, rhs);
  1145. (pIcode+1)->invalidate();
  1146. (pIcode+2)->invalidate();
  1147. pIcode += 3;
  1148. ip += 2;
  1149. }
  1150. else if (idiom16 (pIcode, pEnd))
  1151. {
  1152. lhs = COND_EXPR::idReg (pIcode->ic.ll.dst.regi, pIcode->ic.ll.flg,
  1153. &localId);
  1154. rhs = lhs->clone();
  1155. rhs = COND_EXPR::unary (NEGATION, lhs);
  1156. pIcode->setAsgn(lhs, rhs);
  1157. (pIcode+1)->invalidate();
  1158. (pIcode+2)->invalidate();
  1159. pIcode += 3;
  1160. ip += 2;
  1161. }
  1162. else
  1163. pIcode++;
  1164. break;
  1165. case iNOP:
  1166. (pIcode++)->invalidate();
  1167. break;
  1168. case iENTER: /* ENTER is equivalent to init PUSH bp */
  1169. if (ip == 0)
  1170. flg |= (PROC_HLL | PROC_IS_HLL);
  1171. pIcode++;
  1172. break;
  1173. case iXOR: /* Idiom 7 */
  1174. if (idiom21 (pIcode, pEnd))
  1175. {
  1176. lhs = COND_EXPR::idLong (&localId, DST, pIcode,HIGH_FIRST, ip, eDEF, 1);
  1177. rhs = COND_EXPR::idKte ((pIcode+1)->ic.ll.immed.op , 4);
  1178. pIcode->setAsgn(lhs, rhs);
  1179. pIcode->du.use = 0; /* clear register used in iXOR */
  1180. (pIcode+1)->invalidate();
  1181. pIcode++;
  1182. ip++;
  1183. }
  1184. else if (idiom7 (pIcode))
  1185. {
  1186. lhs = COND_EXPR::id (pIcode, DST, this, ip, pIcode, NONE);
  1187. rhs = COND_EXPR::idKte (0, 2);
  1188. pIcode->setAsgn(lhs, rhs);
  1189. pIcode->du.use = 0; /* clear register used in iXOR */
  1190. pIcode->ic.ll.flg |= I;
  1191. }
  1192. pIcode++;
  1193. break;
  1194. default:
  1195. pIcode++;
  1196. }
  1197. ip++;
  1198. }
  1199. /* Check if number of parameter bytes match their calling convention */
  1200. if ((flg & PROC_HLL) && (!args.sym.empty()))
  1201. {
  1202. args.minOff += (flg & PROC_FAR ? 4 : 2);
  1203. delta = args.maxOff - args.minOff;
  1204. if (cbParam != delta)
  1205. {
  1206. cbParam = delta;
  1207. flg |= (CALL_MASK & CALL_UNKNOWN);
  1208. }
  1209. }
  1210. }
  1211. /* Sets up the TARGET flag for jump target addresses, and
  1212. * binds jump target addresses to icode offsets. */
  1213. void Function::bindIcodeOff()
  1214. {
  1215. Int i, j; /* idx into icode array */
  1216. ICODE * pIcode; /* ptr icode array */
  1217. dword *p; /* for case table */
  1218. if (! Icode.GetNumIcodes()) /* No Icode */
  1219. return;
  1220. pIcode = Icode.GetFirstIcode();
  1221. /* Flag all jump targets for BB construction and disassembly stage 2 */
  1222. for (i = 0; i < Icode.GetNumIcodes(); i++)
  1223. if ((pIcode[i].ic.ll.flg & I) && JmpInst(pIcode[i].ic.ll.opcode))
  1224. {
  1225. if (Icode.labelSrch(pIcode[i].ic.ll.immed.op, &j))
  1226. {
  1227. pIcode[j].ic.ll.flg |= TARGET;
  1228. }
  1229. }
  1230. /* Finally bind jump targets to Icode offsets. Jumps for which no label
  1231. * is found (no code at dest. of jump) are simply left unlinked and
  1232. * flagged as going nowhere. */
  1233. pIcode = Icode.GetFirstIcode();
  1234. for (i = 0; i < Icode.GetNumIcodes(); i++)
  1235. if (JmpInst(pIcode[i].ic.ll.opcode))
  1236. {
  1237. if (pIcode[i].ic.ll.flg & I)
  1238. {
  1239. if (! Icode.labelSrch(pIcode[i].ic.ll.immed.op,
  1240. (Int *)&pIcode[i].ic.ll.immed.op))
  1241. pIcode[i].ic.ll.flg |= NO_LABEL;
  1242. }
  1243. else if (pIcode[i].ic.ll.flg & SWITCH)
  1244. {
  1245. p = pIcode[i].ic.ll.caseTbl.entries;
  1246. for (j = 0; j < pIcode[i].ic.ll.caseTbl.numEntries; j++, p++)
  1247. Icode.labelSrch(*p, (Int *)p);
  1248. }
  1249. }
  1250. }
  1251. /* Performs idioms analysis, and propagates long operands, if any */
  1252. void Function::lowLevelAnalysis ()
  1253. {
  1254. /* Idiom analysis - sets up some flags and creates some HIGH_LEVEL icodes */
  1255. findIdioms();
  1256. /* Propagate HIGH_LEVEL idiom information for long operands */
  1257. propLong();
  1258. }