arith_idioms.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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. byte 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. lhs = COND_EXPR::id (*(pIcode-1), SRC, this, pIcode, *pIcode, eUSE);
  161. if (pIcode->ic.ll.opcode == iDEC)
  162. lhs = COND_EXPR::unary (POST_DEC, lhs);
  163. else
  164. lhs = COND_EXPR::unary (POST_INC, lhs);
  165. rhs = COND_EXPR::id (*(pIcode+1), SRC, this, pIcode, *(pIcode+2), eUSE);
  166. exp = COND_EXPR::boolOp (lhs, rhs, condOpJCond[(pIcode+2)->ic.ll.opcode - iJB]);
  167. (pIcode+2)->setJCond(exp);
  168. (pIcode-1)->invalidate();
  169. pIcode->invalidate();
  170. (pIcode+1)->invalidate();
  171. pIcode += 3;
  172. */
  173. }
  174. /*****************************************************************************
  175. * idiom 19: pre-increment or pre-decrement in conditional jump, comparing against 0.
  176. * [INC | DEC] var (including register vars)
  177. * JX lab JX lab
  178. * => HLI_JCOND (++var X 0) or HLI_JCOND (--var X 0)
  179. * Eg: INC [bp+4]
  180. * JG lab2
  181. * => HLI_JCOND (++[bp+4] > 0)
  182. * Found in Borland Turbo C. Intrinsic to C language.
  183. ****************************************************************************/
  184. bool Idiom19::match(iICODE picode)
  185. {
  186. if(std::distance(picode,m_end)<2)
  187. return false;
  188. for(int i=0; i<2; ++i)
  189. m_icodes[i] =picode++;
  190. m_is_dec = m_icodes[0]->ic.ll.match(iDEC);
  191. if (m_icodes[0]->ic.ll.dst.regi == 0) /* global variable */
  192. /* not supported yet */ ;
  193. else if (m_icodes[0]->ic.ll.dst.regi < INDEXBASE) /* register */
  194. {
  195. // if (((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR)) ||
  196. // ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR)))
  197. if (m_icodes[1]->ic.ll.conditionalJump())
  198. return true;
  199. }
  200. else if (m_icodes[0]->ic.ll.dst.off) /* stack variable */
  201. {
  202. if ( m_icodes[1]->ic.ll.conditionalJump() )
  203. return true;
  204. }
  205. else /* indexed */
  206. /* not supported yet */ ;
  207. return false;
  208. }
  209. int Idiom19::action()
  210. {
  211. COND_EXPR *lhs,*rhs,*expr;
  212. lhs = COND_EXPR::id (*m_icodes[1], DST, m_func, m_icodes[0], *m_icodes[1], eUSE);
  213. lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
  214. rhs = COND_EXPR::idKte (0, 2);
  215. expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[1]->ic.ll.opcode - iJB]);
  216. m_icodes[1]->setJCond(expr);
  217. m_icodes[0]->invalidate();
  218. return 2;
  219. }
  220. /*****************************************************************************
  221. * idiom20: Pre increment/decrement in conditional expression (compares
  222. * against a register, variable or constant different than 0).
  223. * INC var or DEC var (including register vars)
  224. * MOV reg, var MOV reg, var
  225. * CMP reg, Y CMP reg, Y
  226. * JX lab JX lab
  227. * => HLI_JCOND (++var X Y) or HLI_JCOND (--var X Y)
  228. * Eg: INC si (si is a register variable)
  229. * MOV ax, si
  230. * CMP ax, 2
  231. * JL lab4
  232. * => HLI_JCOND (++si < 2)
  233. * Found in Turbo C. Intrinsic to C language.
  234. ****************************************************************************/
  235. bool Idiom20::match(iICODE picode)
  236. {
  237. uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */
  238. byte regi; /* register of the MOV */
  239. if(std::distance(picode,m_end)<4)
  240. return false;
  241. for(int i=0; i<4; ++i)
  242. m_icodes[i] =picode++;
  243. m_is_dec = m_icodes[0]->ic.ll.match(iDEC);
  244. /* Get variable */
  245. if (m_icodes[0]->ic.ll.dst.regi == 0) /* global variable */
  246. {
  247. /* not supported yet */ ;
  248. }
  249. else if (m_icodes[0]->ic.ll.dst.regi < INDEXBASE) /* register */
  250. {
  251. if ((m_icodes[0]->ic.ll.dst.regi == rSI) && (m_func->flg & SI_REGVAR))
  252. type = 1;
  253. else if ((m_icodes[0]->ic.ll.dst.regi == rDI) && (m_func->flg & DI_REGVAR))
  254. type = 1;
  255. }
  256. else if (m_icodes[0]->ic.ll.dst.off) /* local variable */
  257. type = 2;
  258. else /* indexed */
  259. {
  260. printf("idiom20 : Unsupported type\n");
  261. /* not supported yet */ ;
  262. }
  263. /* Check previous instruction for a MOV */
  264. if (type == 1) /* register variable */
  265. {
  266. if (m_icodes[1]->ic.ll.match(iMOV) &&
  267. (m_icodes[1]->ic.ll.src.regi == m_icodes[0]->ic.ll.dst.regi))
  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. else if (type == 2) /* local */
  279. {
  280. if ( m_icodes[0]->ic.ll.match(iMOV) &&
  281. (m_icodes[1]->ic.ll.src.off == m_icodes[0]->ic.ll.dst.off))
  282. {
  283. regi = m_icodes[1]->ic.ll.dst.regi;
  284. if ((regi > 0) && (regi < INDEXBASE))
  285. {
  286. if (m_icodes[2]->ic.ll.match(iCMP,(eReg)regi) &&
  287. m_icodes[3]->ic.ll.conditionalJump())
  288. return true;
  289. }
  290. }
  291. }
  292. return false;
  293. }
  294. int Idiom20::action()
  295. {
  296. COND_EXPR *lhs,*rhs,*expr;
  297. lhs = COND_EXPR::id (*m_icodes[1], SRC, m_func, m_icodes[0], *m_icodes[0], eUSE);
  298. lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
  299. rhs = COND_EXPR::id (*m_icodes[2], SRC, m_func, m_icodes[0], *m_icodes[3], eUSE);
  300. expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ic.ll.opcode - iJB]);
  301. m_icodes[3]->setJCond(expr);
  302. m_icodes[0]->invalidate();
  303. m_icodes[1]->invalidate();
  304. m_icodes[2]->invalidate();
  305. return 4;
  306. }