shift_idioms.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #include "shift_idioms.h"
  2. #include "dcc.h"
  3. #include "msvc_fixes.h"
  4. using namespace std;
  5. /*****************************************************************************
  6. * idiom8 - Shift right by 1 (signed long ops)
  7. * SAR reg, 1
  8. * RCR reg, 1
  9. * Eg: SAR dx, 1
  10. * RCR ax, 1
  11. * => dx:ax = dx:ax >> 1 (dx:ax are signed long)
  12. * Found in Microsoft C code for long signed variable shift right.
  13. ****************************************************************************/
  14. bool Idiom8::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[0]->ll()->testFlags(I) and (m_icodes[0]->ll()->src().getImm2() == 1))
  21. if ( m_icodes[1]->ll()->match(iRCR,I) and
  22. (m_icodes[1]->ll()->src().getImm2() == 1))
  23. return true;
  24. return false;
  25. }
  26. int Idiom8::action()
  27. {
  28. int idx;
  29. AstIdent *lhs;
  30. Expr *expr;
  31. eReg regH,regL;
  32. regH=m_icodes[0]->ll()->m_dst.regi;
  33. regL=m_icodes[1]->ll()->m_dst.regi;
  34. idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(regH,regL), m_icodes[0]);
  35. lhs = AstIdent::LongIdx (idx);
  36. m_icodes[0]->setRegDU( regL, USE_DEF);
  37. expr = new BinaryOperator(SHR,lhs, new Constant(1, 2));
  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. 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().getImm2() != 1))
  60. return false;
  61. m_icodes.clear();
  62. regi = pIcode->ll()->m_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().getImm2() == 1) )
  67. {
  68. m_icodes.push_back(pIcode++);
  69. }
  70. return m_icodes.size()>1;
  71. }
  72. int Idiom15::action()
  73. {
  74. AstIdent *lhs;
  75. Expr *rhs,*_exp;
  76. lhs = new RegisterNode(*m_icodes[0]->ll()->get(DST), &m_func->localId);
  77. rhs = new Constant(m_icodes.size(), 2);
  78. _exp = new BinaryOperator(SHL,lhs, rhs);
  79. m_icodes[0]->setAsgn(lhs, _exp);
  80. for (size_t i=1; i<m_icodes.size()-1; ++i)
  81. {
  82. m_icodes[i]->invalidate();
  83. }
  84. return m_icodes.size();
  85. }
  86. /*****************************************************************************
  87. * idiom12 - Shift left long by 1
  88. * SHL reg, 1
  89. * RCL reg, 1
  90. * Eg: SHL ax, 1
  91. * RCL dx, 1
  92. * => dx:ax = dx:ax << 1
  93. * Found in Borland Turbo C code for long variable shift left.
  94. ****************************************************************************/
  95. bool Idiom12::match(iICODE pIcode)
  96. {
  97. if(distance(pIcode,m_end)<2)
  98. return false;
  99. m_icodes[0]=pIcode++;
  100. m_icodes[1]=pIcode++;
  101. if (m_icodes[0]->ll()->testFlags(I) and (m_icodes[0]->ll()->src().getImm2() == 1))
  102. if (m_icodes[1]->ll()->match(iRCL,I) and (m_icodes[1]->ll()->src().getImm2() == 1))
  103. return true;
  104. return false;
  105. }
  106. int Idiom12::action()
  107. {
  108. int idx;
  109. Expr *expr;
  110. AstIdent *lhs;
  111. eReg regH,regL;
  112. regL=m_icodes[0]->ll()->m_dst.regi;
  113. regH=m_icodes[1]->ll()->m_dst.regi;
  114. idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN, LONGID_TYPE(regH,regL),m_icodes[0]);
  115. lhs = AstIdent::LongIdx (idx);
  116. m_icodes[0]->setRegDU( regH, USE_DEF);
  117. expr = new BinaryOperator(SHL,lhs, new Constant(1, 2));
  118. m_icodes[0]->setAsgn(lhs, expr);
  119. m_icodes[1]->invalidate();
  120. return 2;
  121. }
  122. /*****************************************************************************
  123. * idiom9 - Shift right by 1 (unsigned long ops)
  124. * SHR reg, 1
  125. * RCR reg, 1
  126. * Eg: SHR dx, 1
  127. * RCR ax, 1
  128. * => dx:ax = dx:ax >> 1 (dx:ax are unsigned long)
  129. * Found in Microsoft C code for long unsigned variable shift right.
  130. ****************************************************************************/
  131. bool Idiom9::match(iICODE pIcode)
  132. {
  133. if(distance(pIcode,m_end)<2)
  134. return false;
  135. m_icodes[0]=pIcode++;
  136. m_icodes[1]=pIcode++;
  137. if (m_icodes[0]->ll()->testFlags(I) and (m_icodes[0]->ll()->src().getImm2() == 1))
  138. if (m_icodes[1]->ll()->match(iRCR,I) and (m_icodes[1]->ll()->src().getImm2() == 1))
  139. return true;
  140. return false;
  141. }
  142. int Idiom9::action()
  143. {
  144. int idx;
  145. AstIdent *lhs;
  146. Expr *expr;
  147. eReg regH,regL;
  148. regL=m_icodes[1]->ll()->m_dst.regi;
  149. regH=m_icodes[0]->ll()->m_dst.regi;
  150. idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN,LONGID_TYPE(regH,regL),m_icodes[0]);
  151. lhs = AstIdent::LongIdx (idx);
  152. m_icodes[0]->setRegDU(regL, USE_DEF);
  153. expr = new BinaryOperator(SHR,lhs, new Constant(1, 2));
  154. m_icodes[0]->setAsgn(lhs, expr);
  155. m_icodes[1]->invalidate();
  156. return 2;
  157. }