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