shift_idioms.cpp 5.3 KB

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