149 lines
4.4 KiB
C++
149 lines
4.4 KiB
C++
#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()->isLlFlag(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()->isLlFlag(NO_CODE) && (nicode != m_end))
|
|
{
|
|
nicode++;
|
|
}
|
|
if(nicode == m_end)
|
|
return false;
|
|
|
|
if (nicode->ll()->match(iPOP,rBP) && ! (nicode->ll()->isLlFlag(I | TARGET | CASE)) )
|
|
{
|
|
m_icodes.push_back(nicode++); // Matched POP BP
|
|
|
|
/* Match RET(F) */
|
|
if ( nicode != m_end &&
|
|
!(nicode->ll()->isLlFlag(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()->isLlFlag(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()->isLlFlag(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;
|
|
}
|
|
|