arith_idioms.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. #include "dcc.h"
  2. #include "arith_idioms.h"
  3. using namespace std;
  4. /*****************************************************************************
  5. * idiom5 - Long addition.
  6. * ADD reg/stackOff, reg/stackOff
  7. * ADC reg/stackOff, reg/stackOff
  8. * Eg: ADD ax, [bp-4]
  9. * ADC dx, [bp-2]
  10. * => dx:ax = dx:ax + [bp-2]:[bp-4]
  11. * Found in Borland Turbo C code.
  12. * Commonly used idiom for long addition.
  13. ****************************************************************************/
  14. bool Idiom5::match(iICODE pIcode)
  15. {
  16. if(distance(pIcode,m_end)<2)
  17. return false;
  18. m_icodes[0]=pIcode++;
  19. m_icodes[1]=pIcode++;
  20. if (m_icodes[1]->ll()->match(iADC))
  21. return true;
  22. return false;
  23. }
  24. int Idiom5::action()
  25. {
  26. COND_EXPR *rhs,*lhs,*expr;
  27. lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, m_icodes[1]);
  28. rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, m_icodes[1]);
  29. expr = COND_EXPR::boolOp (lhs, rhs, ADD);
  30. m_icodes[0]->setAsgn(lhs, expr);
  31. m_icodes[1]->invalidate();
  32. return 2;
  33. }
  34. /*****************************************************************************
  35. * idiom6 - Long substraction.
  36. * SUB reg/stackOff, reg/stackOff
  37. * SBB reg/stackOff, reg/stackOff
  38. * Eg: SUB ax, [bp-4]
  39. * SBB dx, [bp-2]
  40. * => dx:ax = dx:ax - [bp-2]:[bp-4]
  41. * Found in Borland Turbo C code.
  42. * Commonly used idiom for long substraction.
  43. ****************************************************************************/
  44. bool Idiom6::match(iICODE pIcode)
  45. {
  46. if(distance(pIcode,m_end)<2)
  47. return false;
  48. m_icodes[0]=pIcode++;
  49. m_icodes[1]=pIcode++;
  50. if (m_icodes[1]->ll()->match(iSBB))
  51. return true;
  52. return false;
  53. }
  54. int Idiom6::action()
  55. {
  56. COND_EXPR *rhs,*lhs,*expr;
  57. lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, m_icodes[1]);
  58. rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, m_icodes[1]);
  59. expr = COND_EXPR::boolOp (lhs, rhs, SUB);
  60. m_icodes[0]->setAsgn(lhs, expr);
  61. m_icodes[1]->invalidate();
  62. return 2;
  63. }
  64. /*****************************************************************************
  65. * idiom 18: Post-increment or post-decrement in a conditional jump
  66. * Used
  67. * 0 MOV reg, var (including register variables)
  68. * 1 INC var or DEC var <------------------------- input point
  69. * 2 CMP var, Y
  70. * 3 JX label
  71. * => HLI_JCOND (var++ X Y)
  72. * Eg: MOV ax, si
  73. * INC si
  74. * CMP ax, 8
  75. * JL labX
  76. * => HLI_JCOND (si++ < 8)
  77. * Found in Borland Turbo C. Intrinsic to C languages.
  78. ****************************************************************************/
  79. bool Idiom18::match(iICODE picode)
  80. {
  81. if(picode==m_func->Icode.begin())
  82. return false;
  83. if(std::distance(picode,m_end)<3)
  84. return false;
  85. --picode; //
  86. for(int i=0; i<4; ++i)
  87. m_icodes[i] =picode++;
  88. m_is_dec = m_icodes[1]->ll()->match(iDEC);
  89. int type = -1; /* type of variable: 1 = reg-var, 2 = local */
  90. uint8_t regi; /* register of the MOV */
  91. /* Get variable */
  92. if (m_icodes[1]->ll()->dst.regi == 0) /* global variable */
  93. {
  94. /* not supported yet */
  95. type = 0;
  96. }
  97. else if (m_icodes[1]->ll()->dst.regi < INDEXBASE) /* register */
  98. {
  99. if ((m_icodes[1]->ll()->dst.regi == rSI) && (m_func->flg & SI_REGVAR))
  100. type = 1;
  101. else if ((m_icodes[1]->ll()->dst.regi == rDI) && (m_func->flg & DI_REGVAR))
  102. type = 1;
  103. }
  104. else if (m_icodes[1]->ll()->dst.off) /* local variable */
  105. type = 2;
  106. else /* indexed */
  107. {
  108. type=3;
  109. /* not supported yet */
  110. printf("Unsupported idiom18 type: indexed");
  111. }
  112. switch(type)
  113. {
  114. case 0: // global
  115. printf("Unsupported idiom18 type: global variable");
  116. break;
  117. case 1: /* register variable */
  118. /* Check previous instruction for a MOV */
  119. if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src.regi == m_icodes[1]->ll()->dst.regi))
  120. {
  121. regi = m_icodes[0]->ll()->dst.regi;
  122. if ((regi > 0) && (regi < INDEXBASE))
  123. {
  124. if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) &&
  125. m_icodes[3]->ll()->conditionalJump() )
  126. return true;
  127. }
  128. }
  129. break;
  130. case 2: /* local */
  131. if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src.off == m_icodes[1]->ll()->dst.off))
  132. {
  133. regi = m_icodes[0]->ll()->dst.regi;
  134. if ((regi > 0) && (regi < INDEXBASE))
  135. {
  136. if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) &&
  137. m_icodes[3]->ll()->conditionalJump() )
  138. return true;
  139. }
  140. }
  141. break;
  142. case 3: // indexed
  143. printf("Unsupported idiom18 type: indexed");
  144. break;
  145. }
  146. return false;
  147. }
  148. int Idiom18::action() // action length
  149. {
  150. COND_EXPR *rhs, *lhs; /* Pointers to left and right hand side exps */
  151. COND_EXPR *expr;
  152. lhs = COND_EXPR::id (*m_icodes[0], SRC, m_func, m_icodes[1], *m_icodes[1], eUSE);
  153. lhs = COND_EXPR::unary ( m_is_dec ? POST_DEC : POST_INC, lhs);
  154. rhs = COND_EXPR::id (*m_icodes[2], SRC, m_func, m_icodes[1], *m_icodes[3], eUSE);
  155. expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]);
  156. m_icodes[3]->setJCond(expr);
  157. m_icodes[0]->invalidate();
  158. m_icodes[1]->invalidate();
  159. m_icodes[2]->invalidate();
  160. return 3;
  161. }
  162. /*****************************************************************************
  163. * idiom 19: pre-increment or pre-decrement in conditional jump, comparing against 0.
  164. * [INC | DEC] var (including register vars)
  165. * JX lab JX lab
  166. * => HLI_JCOND (++var X 0) or HLI_JCOND (--var X 0)
  167. * Eg: INC [bp+4]
  168. * JG lab2
  169. * => HLI_JCOND (++[bp+4] > 0)
  170. * Found in Borland Turbo C. Intrinsic to C language.
  171. ****************************************************************************/
  172. bool Idiom19::match(iICODE picode)
  173. {
  174. if(std::distance(picode,m_end)<2)
  175. return false;
  176. for(int i=0; i<2; ++i)
  177. m_icodes[i] =picode++;
  178. m_is_dec = m_icodes[0]->ll()->match(iDEC);
  179. if (m_icodes[0]->ll()->dst.regi == 0) /* global variable */
  180. /* not supported yet */ ;
  181. else if (m_icodes[0]->ll()->dst.regi < INDEXBASE) /* register */
  182. {
  183. // if (((picode->ll()->dst.regi == rSI) && (pproc->flg & SI_REGVAR)) ||
  184. // ((picode->ll()->dst.regi == rDI) && (pproc->flg & DI_REGVAR)))
  185. if (m_icodes[1]->ll()->conditionalJump())
  186. return true;
  187. }
  188. else if (m_icodes[0]->ll()->dst.off) /* stack variable */
  189. {
  190. if ( m_icodes[1]->ll()->conditionalJump() )
  191. return true;
  192. }
  193. else /* indexed */
  194. /* not supported yet */ ;
  195. return false;
  196. }
  197. int Idiom19::action()
  198. {
  199. COND_EXPR *lhs,*rhs,*expr;
  200. lhs = COND_EXPR::id (*m_icodes[1], DST, m_func, m_icodes[0], *m_icodes[1], eUSE);
  201. lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
  202. rhs = COND_EXPR::idKte (0, 2);
  203. expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[1]->ll()->getOpcode() - iJB]);
  204. m_icodes[1]->setJCond(expr);
  205. m_icodes[0]->invalidate();
  206. return 2;
  207. }
  208. /*****************************************************************************
  209. * idiom20: Pre increment/decrement in conditional expression (compares
  210. * against a register, variable or constant different than 0).
  211. * INC var or DEC var (including register vars)
  212. * MOV reg, var MOV reg, var
  213. * CMP reg, Y CMP reg, Y
  214. * JX lab JX lab
  215. * => HLI_JCOND (++var X Y) or HLI_JCOND (--var X Y)
  216. * Eg: INC si (si is a register variable)
  217. * MOV ax, si
  218. * CMP ax, 2
  219. * JL lab4
  220. * => HLI_JCOND (++si < 2)
  221. * Found in Turbo C. Intrinsic to C language.
  222. ****************************************************************************/
  223. bool Idiom20::match(iICODE picode)
  224. {
  225. uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */
  226. uint8_t regi; /* register of the MOV */
  227. if(std::distance(picode,m_end)<4)
  228. return false;
  229. for(int i=0; i<4; ++i)
  230. m_icodes[i] =picode++;
  231. m_is_dec = m_icodes[0]->ll()->match(iDEC);
  232. /* Get variable */
  233. if (m_icodes[0]->ll()->dst.regi == 0) /* global variable */
  234. {
  235. /* not supported yet */ ;
  236. }
  237. else if (m_icodes[0]->ll()->dst.regi < INDEXBASE) /* register */
  238. {
  239. if ((m_icodes[0]->ll()->dst.regi == rSI) && (m_func->flg & SI_REGVAR))
  240. type = 1;
  241. else if ((m_icodes[0]->ll()->dst.regi == rDI) && (m_func->flg & DI_REGVAR))
  242. type = 1;
  243. }
  244. else if (m_icodes[0]->ll()->dst.off) /* local variable */
  245. type = 2;
  246. else /* indexed */
  247. {
  248. printf("idiom20 : Unsupported type\n");
  249. /* not supported yet */ ;
  250. }
  251. /* Check previous instruction for a MOV */
  252. if (type == 1) /* register variable */
  253. {
  254. if (m_icodes[1]->ll()->match(iMOV) &&
  255. (m_icodes[1]->ll()->src.regi == m_icodes[0]->ll()->dst.regi))
  256. {
  257. regi = m_icodes[1]->ll()->dst.regi;
  258. if ((regi > 0) && (regi < INDEXBASE))
  259. {
  260. if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) &&
  261. m_icodes[3]->ll()->conditionalJump())
  262. return true;
  263. }
  264. }
  265. }
  266. else if (type == 2) /* local */
  267. {
  268. if ( m_icodes[0]->ll()->match(iMOV) &&
  269. (m_icodes[1]->ll()->src.off == m_icodes[0]->ll()->dst.off))
  270. {
  271. regi = m_icodes[1]->ll()->dst.regi;
  272. if ((regi > 0) && (regi < INDEXBASE))
  273. {
  274. if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) &&
  275. m_icodes[3]->ll()->conditionalJump())
  276. return true;
  277. }
  278. }
  279. }
  280. return false;
  281. }
  282. int Idiom20::action()
  283. {
  284. COND_EXPR *lhs,*rhs,*expr;
  285. lhs = COND_EXPR::id (*m_icodes[1], SRC, m_func, m_icodes[0], *m_icodes[0], eUSE);
  286. lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
  287. rhs = COND_EXPR::id (*m_icodes[2], SRC, m_func, m_icodes[0], *m_icodes[3], eUSE);
  288. expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]);
  289. m_icodes[3]->setJCond(expr);
  290. for(int i=0; i<3; ++i)
  291. m_icodes[i]->invalidate();
  292. return 4;
  293. }