epilogue_idioms.cpp 4.5 KB

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