arith_idioms.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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]->ll());
  28. rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
  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]->ll());
  58. rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
  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.isReg() ) /* 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 ( m_icodes[0]->ll()->dst.isReg() )
  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 ( m_icodes[0]->ll()->dst.isReg() )
  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]->ll(), 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]->ll(), 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.isReg() ) /* 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. {
  195. /* not supported yet */
  196. }
  197. return false;
  198. }
  199. int Idiom19::action()
  200. {
  201. COND_EXPR *lhs,*rhs,*expr;
  202. lhs = COND_EXPR::id (*m_icodes[1]->ll(), DST, m_func, m_icodes[0], *m_icodes[1], eUSE);
  203. lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
  204. rhs = COND_EXPR::idKte (0, 2);
  205. expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[1]->ll()->getOpcode() - iJB]);
  206. m_icodes[1]->setJCond(expr);
  207. m_icodes[0]->invalidate();
  208. return 2;
  209. }
  210. /*****************************************************************************
  211. * idiom20: Pre increment/decrement in conditional expression (compares
  212. * against a register, variable or constant different than 0).
  213. * INC var or DEC var (including register vars)
  214. * MOV reg, var MOV reg, var
  215. * CMP reg, Y CMP reg, Y
  216. * JX lab JX lab
  217. * => HLI_JCOND (++var X Y) or HLI_JCOND (--var X Y)
  218. * Eg: INC si (si is a register variable)
  219. * MOV ax, si
  220. * CMP ax, 2
  221. * JL lab4
  222. * => HLI_JCOND (++si < 2)
  223. * Found in Turbo C. Intrinsic to C language.
  224. ****************************************************************************/
  225. bool Idiom20::match(iICODE picode)
  226. {
  227. uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */
  228. uint8_t regi; /* register of the MOV */
  229. if(std::distance(picode,m_end)<4)
  230. return false;
  231. for(int i=0; i<4; ++i)
  232. m_icodes[i] =picode++;
  233. m_is_dec = m_icodes[0]->ll()->match(iDEC);
  234. LLOperand &ll_dest(m_icodes[0]->ll()->dst);
  235. /* Get variable */
  236. if (ll_dest.regi == 0) /* global variable */
  237. {
  238. /* not supported yet */ ;
  239. }
  240. else if ( ll_dest.isReg() ) /* register */
  241. {
  242. if ((ll_dest.regi == rSI) && (m_func->flg & SI_REGVAR))
  243. type = 1;
  244. else if ((ll_dest.regi == rDI) && (m_func->flg & DI_REGVAR))
  245. type = 1;
  246. }
  247. else if (ll_dest.off) /* local variable */
  248. type = 2;
  249. else /* indexed */
  250. {
  251. printf("idiom20 : Unsupported type [indexed]\n");
  252. /* not supported yet */ ;
  253. }
  254. /* Check previous instruction for a MOV */
  255. if (type == 1) /* register variable */
  256. {
  257. if (m_icodes[1]->ll()->match(iMOV) &&
  258. (m_icodes[1]->ll()->src().regi == ll_dest.regi))
  259. {
  260. regi = m_icodes[1]->ll()->dst.regi;
  261. if ( m_icodes[1]->ll()->dst.isReg() )
  262. {
  263. if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) &&
  264. m_icodes[3]->ll()->conditionalJump())
  265. return true;
  266. }
  267. }
  268. }
  269. else if (type == 2) /* local */
  270. {
  271. if ( m_icodes[0]->ll()->match(iMOV) &&
  272. (m_icodes[1]->ll()->src().off == ll_dest.off))
  273. {
  274. regi = m_icodes[1]->ll()->dst.regi;
  275. if ( m_icodes[1]->ll()->dst.isReg() )
  276. {
  277. if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) &&
  278. m_icodes[3]->ll()->conditionalJump())
  279. return true;
  280. }
  281. }
  282. }
  283. return false;
  284. }
  285. int Idiom20::action()
  286. {
  287. COND_EXPR *lhs,*rhs,*expr;
  288. lhs = COND_EXPR::id (*m_icodes[1]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], eUSE);
  289. lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
  290. rhs = COND_EXPR::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[0], *m_icodes[3], eUSE);
  291. expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]);
  292. m_icodes[3]->setJCond(expr);
  293. for(int i=0; i<3; ++i)
  294. m_icodes[i]->invalidate();
  295. return 4;
  296. }