123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- #include "dcc.h"
- #include "epilogue_idioms.h"
- /*****************************************************************************
- * popStkVars - checks for
- * [POP DI]
- * [POP SI]
- * or [POP SI]
- * [POP DI]
- ****************************************************************************/
- void EpilogIdiom::popStkVars(iICODE pIcode)
- {
- // TODO : only process SI-DI DI-SI pairings, no SI-SI, DI-DI like it's now
- /* Match [POP DI] */
- if (pIcode->ll()->match(iPOP))
- {
- if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI))
- m_icodes.push_front(pIcode);
- else if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI))
- m_icodes.push_front(pIcode);
- }
- ++pIcode;
- if(pIcode==m_end)
- return;
- /* Match [POP SI] */
- if (pIcode->ll()->match(iPOP))
- {
- if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI))
- m_icodes.push_front(pIcode);
- else if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI))
- m_icodes.push_front(pIcode);
- }
- }
- /*****************************************************************************
- * idiom2 - HLL procedure epilogue; Returns number of instructions matched.
- * [POP DI]
- * [POP SI]
- * MOV SP, BP
- * POP BP
- * RET(F)
- *****************************************************************************/
- bool Idiom2::match(iICODE pIcode)
- {
- iICODE nicode;
- if(pIcode==m_func->Icode.begin()) // pIcode->loc_ip == 0
- return false;
- if ( pIcode->ll()->testFlags(I) || (not pIcode->ll()->match(rSP,rBP)) )
- return false;
- if(distance(pIcode,m_end)<3)
- return false;
- /* Matched MOV SP, BP */
- m_icodes.clear();
- m_icodes.push_back(pIcode);
- /* Get next icode, skip over holes in the icode array */
- nicode = ++iICODE(pIcode);
- while (nicode->ll()->testFlags(NO_CODE) && (nicode != m_end))
- {
- nicode++;
- }
- if(nicode == m_end)
- return false;
- if (nicode->ll()->match(iPOP,rBP) && ! (nicode->ll()->testFlags(I | TARGET | CASE)) )
- {
- m_icodes.push_back(nicode++); // Matched POP BP
- /* Match RET(F) */
- if ( nicode != m_end &&
- !(nicode->ll()->testFlags(I | TARGET | CASE)) &&
- (nicode->ll()->match(iRET) || nicode->ll()->match(iRETF))
- )
- {
- m_icodes.push_back(nicode); // Matched RET
- advance(pIcode,-2); // move back before our start
- popStkVars (pIcode); // and add optional pop di/si to m_icodes
- return true;
- }
- }
- return false;
- }
- int Idiom2::action()
- {
- for(size_t idx=0; idx<m_icodes.size()-1; ++idx) // don't invalidate last entry
- m_icodes[idx]->invalidate();
- return 3;
- }
- /*****************************************************************************
- * idiom4 - Pascal calling convention.
- * RET(F) immed
- * ==> pProc->cbParam = immed
- * sets CALL_PASCAL flag
- * - Second version: check for optional pop of stack vars
- * [POP DI]
- * [POP SI]
- * POP BP
- * RET(F) [immed]
- * - Third version: pop stack vars
- * [POP DI]
- * [POP SI]
- * RET(F) [immed]
- ****************************************************************************/
- bool Idiom4::match(iICODE pIcode)
- {
- m_param_count = 0;
- /* Check for [POP DI]
- * [POP SI] */
- if(distance(m_func->Icode.begin(),pIcode)>=3)
- {
- iICODE search_at(pIcode);
- advance(search_at,-3);
- popStkVars(search_at);
- }
- if(pIcode != m_func->Icode.begin())
- {
- iICODE prev1 = --iICODE(pIcode);
- /* Check for POP BP */
- if (prev1->ll()->match(iPOP,rBP) && not prev1->ll()->testFlags(I) )
- m_icodes.push_back(prev1);
- else if(prev1!=m_func->Icode.begin())
- {
- iICODE search_at(pIcode);
- advance(search_at,-2);
- popStkVars (search_at);
- }
- }
- /* Check for RET(F) immed */
- if (pIcode->ll()->testFlags(I) )
- {
- m_param_count = (int16_t)pIcode->ll()->src.op();
- }
- }
- int Idiom4::action()
- {
- for(size_t idx=0; idx<m_icodes.size()-1; ++idx) // don't invalidate last entry
- m_icodes[idx]->invalidate();
- if(m_param_count)
- {
- m_func->cbParam = (int16_t)m_param_count;
- m_func->flg |= CALL_PASCAL;
- }
- return 1;
- }
|