epilogue_idioms.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #include "dcc.h"
  2. #include "epilogue_idioms.h"
  3. /*****************************************************************************
  4. * popStkVars - checks for
  5. * [POP DI]
  6. * [POP SI]
  7. * or [POP SI]
  8. * [POP DI]
  9. ****************************************************************************/
  10. void EpilogIdiom::popStkVars(iICODE pIcode)
  11. {
  12. // TODO : only process SI-DI DI-SI pairings, no SI-SI, DI-DI like it's now
  13. /* Match [POP DI] */
  14. if (pIcode->ll()->match(iPOP))
  15. {
  16. if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI))
  17. m_icodes.push_front(pIcode);
  18. else if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI))
  19. m_icodes.push_front(pIcode);
  20. }
  21. ++pIcode;
  22. if(pIcode==m_end)
  23. return;
  24. /* Match [POP SI] */
  25. if (pIcode->ll()->match(iPOP))
  26. {
  27. if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI))
  28. m_icodes.push_front(pIcode);
  29. else if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI))
  30. m_icodes.push_front(pIcode);
  31. }
  32. }
  33. /*****************************************************************************
  34. * idiom2 - HLL procedure epilogue; Returns number of instructions matched.
  35. * [POP DI]
  36. * [POP SI]
  37. * MOV SP, BP
  38. * POP BP
  39. * RET(F)
  40. *****************************************************************************/
  41. bool Idiom2::match(iICODE pIcode)
  42. {
  43. iICODE nicode;
  44. if(pIcode==m_func->Icode.begin()) // pIcode->loc_ip == 0
  45. return false;
  46. if ( pIcode->ll()->testFlags(I) || (not pIcode->ll()->match(rSP,rBP)) )
  47. return false;
  48. if(distance(pIcode,m_end)<3)
  49. return false;
  50. /* Matched MOV SP, BP */
  51. m_icodes.clear();
  52. m_icodes.push_back(pIcode);
  53. /* Get next icode, skip over holes in the icode array */
  54. nicode = ++iICODE(pIcode);
  55. while (nicode->ll()->testFlags(NO_CODE) && (nicode != m_end))
  56. {
  57. nicode++;
  58. }
  59. if(nicode == m_end)
  60. return false;
  61. if (nicode->ll()->match(iPOP,rBP) && ! (nicode->ll()->testFlags(I | TARGET | CASE)) )
  62. {
  63. m_icodes.push_back(nicode++); // Matched POP BP
  64. /* Match RET(F) */
  65. if ( nicode != m_end &&
  66. !(nicode->ll()->testFlags(I | TARGET | CASE)) &&
  67. (nicode->ll()->match(iRET) || nicode->ll()->match(iRETF))
  68. )
  69. {
  70. m_icodes.push_back(nicode); // Matched RET
  71. advance(pIcode,-2); // move back before our start
  72. popStkVars (pIcode); // and add optional pop di/si to m_icodes
  73. return true;
  74. }
  75. }
  76. return false;
  77. }
  78. int Idiom2::action()
  79. {
  80. for(size_t idx=0; idx<m_icodes.size()-1; ++idx) // don't invalidate last entry
  81. m_icodes[idx]->invalidate();
  82. return 3;
  83. }
  84. /*****************************************************************************
  85. * idiom4 - Pascal calling convention.
  86. * RET(F) immed
  87. * ==> pProc->cbParam = immed
  88. * sets CALL_PASCAL flag
  89. * - Second version: check for optional pop of stack vars
  90. * [POP DI]
  91. * [POP SI]
  92. * POP BP
  93. * RET(F) [immed]
  94. * - Third version: pop stack vars
  95. * [POP DI]
  96. * [POP SI]
  97. * RET(F) [immed]
  98. ****************************************************************************/
  99. bool Idiom4::match(iICODE pIcode)
  100. {
  101. m_param_count = 0;
  102. /* Check for [POP DI]
  103. * [POP SI] */
  104. if(distance(m_func->Icode.begin(),pIcode)>=3)
  105. {
  106. iICODE search_at(pIcode);
  107. advance(search_at,-3);
  108. popStkVars(search_at);
  109. }
  110. if(pIcode != m_func->Icode.begin())
  111. {
  112. iICODE prev1 = --iICODE(pIcode);
  113. /* Check for POP BP */
  114. if (prev1->ll()->match(iPOP,rBP) && not prev1->ll()->testFlags(I) )
  115. m_icodes.push_back(prev1);
  116. else if(prev1!=m_func->Icode.begin())
  117. {
  118. iICODE search_at(pIcode);
  119. advance(search_at,-2);
  120. popStkVars (search_at);
  121. }
  122. }
  123. /* Check for RET(F) immed */
  124. if (pIcode->ll()->testFlags(I) )
  125. {
  126. m_param_count = (int16_t)pIcode->ll()->src().getImm2();
  127. return true;
  128. }
  129. return false;
  130. }
  131. int Idiom4::action()
  132. {
  133. if( ! m_icodes.empty()) // if not an empty RET[F] N
  134. {
  135. for(size_t idx=0; idx<m_icodes.size()-1; ++idx) // don't invalidate last entry
  136. m_icodes[idx]->invalidate();
  137. }
  138. if(m_param_count)
  139. {
  140. m_func->cbParam = (int16_t)m_param_count;
  141. m_func->callingConv(CConv::PASCAL);
  142. }
  143. return 1;
  144. }