arith_idioms.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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]->ic.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, 1);
  28. rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, 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]->ic.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, 1);
  58. rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, 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(std::distance(picode,m_end)<3)
  82. return false;
  83. --picode; //
  84. for(int i=0; i<4; ++i)
  85. m_icodes[i] =picode++;
  86. m_is_dec = m_icodes[1]->ic.ll.match(iDEC);
  87. int type = -1; /* type of variable: 1 = reg-var, 2 = local */
  88. uint8_t regi; /* register of the MOV */
  89. /* Get variable */
  90. if (m_icodes[1]->ic.ll.dst.regi == 0) /* global variable */
  91. {
  92. /* not supported yet */
  93. type = 0;
  94. }
  95. else if (m_icodes[1]->ic.ll.dst.regi < INDEXBASE) /* register */
  96. {
  97. if ((m_icodes[1]->ic.ll.dst.regi == rSI) && (m_func->flg & SI_REGVAR))
  98. type = 1;
  99. else if ((m_icodes[1]->ic.ll.dst.regi == rDI) && (m_func->flg & DI_REGVAR))
  100. type = 1;
  101. }
  102. else if (m_icodes[1]->ic.ll.dst.off) /* local variable */
  103. type = 2;
  104. else /* indexed */
  105. {
  106. type=3;
  107. /* not supported yet */
  108. printf("Unsupported idiom18 type: indexed");
  109. }
  110. switch(type)
  111. {
  112. case 0: // global
  113. printf("Unsupported idiom18 type: global variable");
  114. break;
  115. case 1: /* register variable */
  116. /* Check previous instruction for a MOV */
  117. if (m_icodes[0]->ic.ll.match(iMOV) && (m_icodes[0]->ic.ll.src.regi == m_icodes[1]->ic.ll.dst.regi))
  118. {
  119. regi = m_icodes[0]->ic.ll.dst.regi;
  120. if ((regi > 0) && (regi < INDEXBASE))
  121. {
  122. if ( m_icodes[2]->ic.ll.match(iCMP) && (m_icodes[2]->ic.ll.dst.regi == regi) &&
  123. m_icodes[3]->ic.ll.conditionalJump() )
  124. return true;
  125. }
  126. }
  127. break;
  128. case 2: /* local */
  129. if (m_icodes[0]->ic.ll.match(iMOV) && (m_icodes[0]->ic.ll.src.off == m_icodes[1]->ic.ll.dst.off))
  130. {
  131. regi = m_icodes[0]->ic.ll.dst.regi;
  132. if ((regi > 0) && (regi < INDEXBASE))
  133. {
  134. if ( m_icodes[2]->ic.ll.match(iCMP) && (m_icodes[2]->ic.ll.dst.regi == regi) &&
  135. m_icodes[3]->ic.ll.conditionalJump() )
  136. return true;
  137. }
  138. }
  139. break;
  140. case 3: // indexed
  141. printf("Unsupported idiom18 type: indexed");
  142. break;
  143. }
  144. return false;
  145. }
  146. int Idiom18::action() // action length
  147. {
  148. COND_EXPR *rhs, *lhs; /* Pointers to left and right hand side exps */
  149. COND_EXPR *expr;
  150. lhs = COND_EXPR::id (*m_icodes[0], SRC, m_func, m_icodes[1], *m_icodes[1], eUSE);
  151. lhs = COND_EXPR::unary ( m_is_dec ? POST_DEC : POST_INC, lhs);
  152. rhs = COND_EXPR::id (*m_icodes[2], SRC, m_func, m_icodes[1], *m_icodes[3], eUSE);
  153. expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ic.ll.opcode - iJB]);
  154. m_icodes[3]->setJCond(expr);
  155. m_icodes[0]->invalidate();
  156. m_icodes[1]->invalidate();
  157. m_icodes[2]->invalidate();
  158. return 3;
  159. }
  160. /*****************************************************************************
  161. * idiom 19: pre-increment or pre-decrement in conditional jump, comparing against 0.
  162. * [INC | DEC] var (including register vars)
  163. * JX lab JX lab
  164. * => HLI_JCOND (++var X 0) or HLI_JCOND (--var X 0)
  165. * Eg: INC [bp+4]
  166. * JG lab2
  167. * => HLI_JCOND (++[bp+4] > 0)
  168. * Found in Borland Turbo C. Intrinsic to C language.
  169. ****************************************************************************/
  170. bool Idiom19::match(iICODE picode)
  171. {
  172. if(std::distance(picode,m_end)<2)
  173. return false;
  174. for(int i=0; i<2; ++i)
  175. m_icodes[i] =picode++;
  176. m_is_dec = m_icodes[0]->ic.ll.match(iDEC);
  177. if (m_icodes[0]->ic.ll.dst.regi == 0) /* global variable */
  178. /* not supported yet */ ;
  179. else if (m_icodes[0]->ic.ll.dst.regi < INDEXBASE) /* register */
  180. {
  181. // if (((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR)) ||
  182. // ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR)))
  183. if (m_icodes[1]->ic.ll.conditionalJump())
  184. return true;
  185. }
  186. else if (m_icodes[0]->ic.ll.dst.off) /* stack variable */
  187. {
  188. if ( m_icodes[1]->ic.ll.conditionalJump() )
  189. return true;
  190. }
  191. else /* indexed */
  192. /* not supported yet */ ;
  193. return false;
  194. }
  195. int Idiom19::action()
  196. {
  197. COND_EXPR *lhs,*rhs,*expr;
  198. lhs = COND_EXPR::id (*m_icodes[1], DST, m_func, m_icodes[0], *m_icodes[1], eUSE);
  199. lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
  200. rhs = COND_EXPR::idKte (0, 2);
  201. expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[1]->ic.ll.opcode - iJB]);
  202. m_icodes[1]->setJCond(expr);
  203. m_icodes[0]->invalidate();
  204. return 2;
  205. }
  206. /*****************************************************************************
  207. * idiom20: Pre increment/decrement in conditional expression (compares
  208. * against a register, variable or constant different than 0).
  209. * INC var or DEC var (including register vars)
  210. * MOV reg, var MOV reg, var
  211. * CMP reg, Y CMP reg, Y
  212. * JX lab JX lab
  213. * => HLI_JCOND (++var X Y) or HLI_JCOND (--var X Y)
  214. * Eg: INC si (si is a register variable)
  215. * MOV ax, si
  216. * CMP ax, 2
  217. * JL lab4
  218. * => HLI_JCOND (++si < 2)
  219. * Found in Turbo C. Intrinsic to C language.
  220. ****************************************************************************/
  221. bool Idiom20::match(iICODE picode)
  222. {
  223. uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */
  224. uint8_t regi; /* register of the MOV */
  225. if(std::distance(picode,m_end)<4)
  226. return false;
  227. for(int i=0; i<4; ++i)
  228. m_icodes[i] =picode++;
  229. m_is_dec = m_icodes[0]->ic.ll.match(iDEC);
  230. /* Get variable */
  231. if (m_icodes[0]->ic.ll.dst.regi == 0) /* global variable */
  232. {
  233. /* not supported yet */ ;
  234. }
  235. else if (m_icodes[0]->ic.ll.dst.regi < INDEXBASE) /* register */
  236. {
  237. if ((m_icodes[0]->ic.ll.dst.regi == rSI) && (m_func->flg & SI_REGVAR))
  238. type = 1;
  239. else if ((m_icodes[0]->ic.ll.dst.regi == rDI) && (m_func->flg & DI_REGVAR))
  240. type = 1;
  241. }
  242. else if (m_icodes[0]->ic.ll.dst.off) /* local variable */
  243. type = 2;
  244. else /* indexed */
  245. {
  246. printf("idiom20 : Unsupported type\n");
  247. /* not supported yet */ ;
  248. }
  249. /* Check previous instruction for a MOV */
  250. if (type == 1) /* register variable */
  251. {
  252. if (m_icodes[1]->ic.ll.match(iMOV) &&
  253. (m_icodes[1]->ic.ll.src.regi == m_icodes[0]->ic.ll.dst.regi))
  254. {
  255. regi = m_icodes[1]->ic.ll.dst.regi;
  256. if ((regi > 0) && (regi < INDEXBASE))
  257. {
  258. if (m_icodes[2]->ic.ll.match(iCMP,(eReg)regi) &&
  259. m_icodes[3]->ic.ll.conditionalJump())
  260. return true;
  261. }
  262. }
  263. }
  264. else if (type == 2) /* local */
  265. {
  266. if ( m_icodes[0]->ic.ll.match(iMOV) &&
  267. (m_icodes[1]->ic.ll.src.off == m_icodes[0]->ic.ll.dst.off))
  268. {
  269. regi = m_icodes[1]->ic.ll.dst.regi;
  270. if ((regi > 0) && (regi < INDEXBASE))
  271. {
  272. if (m_icodes[2]->ic.ll.match(iCMP,(eReg)regi) &&
  273. m_icodes[3]->ic.ll.conditionalJump())
  274. return true;
  275. }
  276. }
  277. }
  278. return false;
  279. }
  280. int Idiom20::action()
  281. {
  282. COND_EXPR *lhs,*rhs,*expr;
  283. lhs = COND_EXPR::id (*m_icodes[1], SRC, m_func, m_icodes[0], *m_icodes[0], eUSE);
  284. lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
  285. rhs = COND_EXPR::id (*m_icodes[2], SRC, m_func, m_icodes[0], *m_icodes[3], eUSE);
  286. expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ic.ll.opcode - iJB]);
  287. m_icodes[3]->setJCond(expr);
  288. for(int i=0; i<3; ++i)
  289. m_icodes[i]->invalidate();
  290. return 4;
  291. }