shift_idioms.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #include "dcc.h"
  2. #include "shift_idioms.h"
  3. using namespace std;
  4. /*****************************************************************************
  5. * idiom8 - Shift right by 1 (signed long ops)
  6. * SAR reg, 1
  7. * RCR reg, 1
  8. * Eg: SAR dx, 1
  9. * RCR ax, 1
  10. * => dx:ax = dx:ax >> 1 (dx:ax are signed long)
  11. * Found in Microsoft C code for long signed variable shift right.
  12. ****************************************************************************/
  13. bool Idiom8::match(iICODE pIcode)
  14. {
  15. if(distance(pIcode,m_end)<2)
  16. return false;
  17. m_icodes[0]=pIcode++;
  18. m_icodes[1]=pIcode++;
  19. if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src.op() == 1))
  20. if ( m_icodes[1]->ll()->match(iRCR,I) &&
  21. (m_icodes[1]->ll()->src.op() == 1))
  22. return true;
  23. return false;
  24. }
  25. int Idiom8::action()
  26. {
  27. int idx;
  28. COND_EXPR *rhs,*lhs,*expr;
  29. eReg regH,regL;
  30. regH=m_icodes[0]->ll()->dst.regi;
  31. regL=m_icodes[1]->ll()->dst.regi;
  32. idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, regH, regL, m_icodes[0]);
  33. lhs = COND_EXPR::idLongIdx (idx);
  34. m_icodes[0]->setRegDU( regL, USE_DEF);
  35. rhs = COND_EXPR::idKte(1,2);
  36. expr = COND_EXPR::boolOp(lhs, rhs, SHR);
  37. m_icodes[0]->setAsgn(lhs, expr);
  38. m_icodes[1]->invalidate();
  39. return 2;
  40. }
  41. /*****************************************************************************
  42. * idiom 15 - Shift left by n
  43. * SHL reg, 1
  44. * SHL reg, 1
  45. * [...]
  46. * [SHL reg, 1]
  47. * Eg: SHL ax, 1
  48. * SHL ax, 1
  49. * => ax = ax << 2
  50. * Found in Borland Turbo C code to index an array (array multiplication)
  51. ****************************************************************************/
  52. bool Idiom15::match(iICODE pIcode)
  53. {
  54. int n = 1;
  55. uint8_t regi;
  56. if(distance(pIcode,m_end)<2)
  57. return false;
  58. /* Match SHL reg, 1 */
  59. if (not pIcode->ll()->testFlags(I) or (pIcode->ll()->src.op() != 1))
  60. return false;
  61. m_icodes.clear();
  62. regi = pIcode->ll()->dst.regi;
  63. m_icodes.push_back(pIcode++);
  64. while( (pIcode!=m_end) and
  65. pIcode->ll()->match(iSHL,(eReg)regi,I) and
  66. (pIcode->ll()->src.op() == 1) )
  67. {
  68. n++;
  69. m_icodes.push_back(pIcode++);
  70. }
  71. return m_icodes.size()>1;
  72. }
  73. int Idiom15::action()
  74. {
  75. COND_EXPR *lhs,*rhs,*exp;
  76. lhs = COND_EXPR::idReg (m_icodes[0]->ll()->dst.regi,
  77. m_icodes[0]->ll()->getFlag() & NO_SRC_B,
  78. &m_func->localId);
  79. rhs = COND_EXPR::idKte (m_icodes.size(), 2);
  80. exp = COND_EXPR::boolOp (lhs, rhs, SHL);
  81. m_icodes[0]->setAsgn(lhs, exp);
  82. for (size_t i=1; i<m_icodes.size()-1; ++i)
  83. {
  84. m_icodes[i]->invalidate();
  85. }
  86. return m_icodes.size();
  87. }
  88. /*****************************************************************************
  89. * idiom12 - Shift left long by 1
  90. * SHL reg, 1
  91. * RCL reg, 1
  92. * Eg: SHL ax, 1
  93. * RCL dx, 1
  94. * => dx:ax = dx:ax << 1
  95. * Found in Borland Turbo C code for long variable shift left.
  96. ****************************************************************************/
  97. bool Idiom12::match(iICODE pIcode)
  98. {
  99. if(distance(pIcode,m_end)<2)
  100. return false;
  101. m_icodes[0]=pIcode++;
  102. m_icodes[1]=pIcode++;
  103. if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src.op() == 1))
  104. if (m_icodes[1]->ll()->match(iRCL,I) && (m_icodes[1]->ll()->src.op() == 1))
  105. return true;
  106. return false;
  107. }
  108. int Idiom12::action()
  109. {
  110. int idx;
  111. COND_EXPR *rhs,*lhs,*expr;
  112. eReg regH,regL;
  113. regL=m_icodes[0]->ll()->dst.regi;
  114. regH=m_icodes[1]->ll()->dst.regi;
  115. idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN, regH, regL,m_icodes[0]);
  116. lhs = COND_EXPR::idLongIdx (idx);
  117. m_icodes[0]->setRegDU( regH, USE_DEF);
  118. rhs = COND_EXPR::idKte (1, 2);
  119. expr = COND_EXPR::boolOp (lhs, rhs, SHL);
  120. m_icodes[0]->setAsgn(lhs, expr);
  121. m_icodes[1]->invalidate();
  122. return 2;
  123. }
  124. /*****************************************************************************
  125. * idiom9 - Shift right by 1 (unsigned long ops)
  126. * SHR reg, 1
  127. * RCR reg, 1
  128. * Eg: SHR dx, 1
  129. * RCR ax, 1
  130. * => dx:ax = dx:ax >> 1 (dx:ax are unsigned long)
  131. * Found in Microsoft C code for long unsigned variable shift right.
  132. ****************************************************************************/
  133. bool Idiom9::match(iICODE pIcode)
  134. {
  135. if(distance(pIcode,m_end)<2)
  136. return false;
  137. m_icodes[0]=pIcode++;
  138. m_icodes[1]=pIcode++;
  139. if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src.op() == 1))
  140. if (m_icodes[1]->ll()->match(iRCR,I) && (m_icodes[1]->ll()->src.op() == 1))
  141. return true;
  142. return false;
  143. }
  144. int Idiom9::action()
  145. {
  146. int idx;
  147. COND_EXPR *rhs,*lhs,*expr;
  148. eReg regH,regL;
  149. regL=m_icodes[1]->ll()->dst.regi;
  150. regH=m_icodes[0]->ll()->dst.regi;
  151. idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN,regH,regL,m_icodes[0]);
  152. lhs = COND_EXPR::idLongIdx (idx);
  153. m_icodes[0]->setRegDU(regL, USE_DEF);
  154. rhs = COND_EXPR::idKte (1, 2);
  155. expr = COND_EXPR::boolOp (lhs, rhs, SHR);
  156. m_icodes[0]->setAsgn(lhs, expr);
  157. m_icodes[1]->invalidate();
  158. return 2;
  159. }