arith_idioms.cpp 11 KB

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