arith_idioms.cpp 11 KB

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