Refactoring idioms into objects with match/action methods
This commit is contained in:
parent
bf2d099cd9
commit
11ae65efba
39
include/epilogue_idioms.h
Normal file
39
include/epilogue_idioms.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
struct EpilogIdiom : public Idiom
|
||||
{
|
||||
protected:
|
||||
std::deque<iICODE> m_icodes; // deque to push_front optional icodes from popStkVars
|
||||
void popStkVars (iICODE pIcode);
|
||||
public:
|
||||
virtual ~EpilogIdiom() {}
|
||||
EpilogIdiom(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
struct Idiom2 : public EpilogIdiom
|
||||
{
|
||||
virtual ~Idiom2() {}
|
||||
Idiom2(Function *f) : EpilogIdiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 3;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
struct Idiom4 : public EpilogIdiom
|
||||
{
|
||||
protected:
|
||||
int m_param_count;
|
||||
public:
|
||||
virtual ~Idiom4() {}
|
||||
Idiom4(Function *f) : EpilogIdiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 1;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
15
include/idiom.h
Normal file
15
include/idiom.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "icode.h"
|
||||
#include "Procedure.h"
|
||||
struct Idiom
|
||||
{
|
||||
protected:
|
||||
Function *m_func;
|
||||
iICODE m_end;
|
||||
public:
|
||||
Idiom(Function *f) : m_func(f),m_end(f->Icode.end())
|
||||
{
|
||||
}
|
||||
virtual uint8_t minimum_match_length()=0;
|
||||
virtual bool match(iICODE at)=0;
|
||||
};
|
||||
16
include/idiom1.h
Normal file
16
include/idiom1.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include "idiom.h"
|
||||
struct Idiom1 : public Idiom
|
||||
{
|
||||
protected:
|
||||
std::vector<iICODE> m_icodes;
|
||||
int m_min_off;
|
||||
Int checkStkVars (iICODE pIcode);
|
||||
public:
|
||||
Idiom1(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 1;}
|
||||
bool match(iICODE picode);
|
||||
int action();
|
||||
};
|
||||
139
src/epilogue_idioms.cpp
Normal file
139
src/epilogue_idioms.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
#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->ic.ll.match(iPOP))
|
||||
{
|
||||
if ((m_func->flg & DI_REGVAR) && pIcode->ic.ll.match(rDI))
|
||||
m_icodes.push_front(pIcode);
|
||||
else if ((m_func->flg & SI_REGVAR) && pIcode->ic.ll.match(rSI))
|
||||
m_icodes.push_front(pIcode);
|
||||
}
|
||||
++pIcode;
|
||||
if(pIcode==m_end)
|
||||
return;
|
||||
/* Match [POP SI] */
|
||||
if (pIcode->ic.ll.match(iPOP))
|
||||
{
|
||||
if ((m_func->flg & SI_REGVAR) && pIcode->ic.ll.match(rSI))
|
||||
m_icodes.push_front(pIcode);
|
||||
else if ((m_func->flg & DI_REGVAR) && pIcode->ic.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->ic.ll.flg & I) == I) || not pIcode->ic.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 = pIcode + 1;
|
||||
while (nicode->ic.ll.flg & NO_CODE && (nicode != m_end))
|
||||
{
|
||||
nicode++;
|
||||
}
|
||||
if(nicode == m_end)
|
||||
return false;
|
||||
|
||||
if (nicode->ic.ll.match(iPOP,rBP) && ! (nicode->ic.ll.flg & (I | TARGET | CASE)) )
|
||||
{
|
||||
m_icodes.push_back(nicode++); // Matched POP BP
|
||||
|
||||
/* Match RET(F) */
|
||||
if ( nicode != m_end &&
|
||||
!(nicode->ic.ll.flg & (I | TARGET | CASE)) &&
|
||||
(nicode->ic.ll.match(iRET) || nicode->ic.ll.match(iRETF))
|
||||
)
|
||||
{
|
||||
m_icodes.push_back(nicode); // Matched RET
|
||||
popStkVars (pIcode-2); // will 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)
|
||||
popStkVars (pIcode-3);
|
||||
if(pIcode != m_func->Icode.begin())
|
||||
{
|
||||
iICODE prev1=pIcode-1;
|
||||
/* Check for POP BP */
|
||||
if (prev1->ic.ll.match(iPOP,rBP) && not prev1->ic.ll.anyFlagSet(I) )
|
||||
m_icodes.push_back(prev1);
|
||||
else if(prev1!=m_func->Icode.begin())
|
||||
popStkVars (pIcode-2);
|
||||
}
|
||||
|
||||
/* Check for RET(F) immed */
|
||||
if (pIcode->ic.ll.flg & I)
|
||||
{
|
||||
m_param_count = (int16)pIcode->ic.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)m_param_count;
|
||||
m_func->flg |= CALL_PASCAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
132
src/idiom1.cpp
Normal file
132
src/idiom1.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
#include "idiom1.h"
|
||||
#include "dcc.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom1 - HLL procedure prologue; Returns number of instructions matched.
|
||||
* PUSH BP ==> ENTER immed, 0
|
||||
* MOV BP, SP and sets PROC_HLL flag
|
||||
* [SUB SP, immed]
|
||||
* [PUSH SI]
|
||||
* [PUSH DI]
|
||||
* - Second version: Push stack variables and then save BP
|
||||
* PUSH BP
|
||||
* PUSH SI
|
||||
* [PUSH DI]
|
||||
* MOV BP, SP
|
||||
* - Third version: Stack variables
|
||||
* [PUSH SI]
|
||||
* [PUSH DI]
|
||||
****************************************************************************/
|
||||
/*****************************************************************************
|
||||
/* checkStkVars - Checks for PUSH SI
|
||||
* [PUSH DI]
|
||||
* or PUSH DI
|
||||
* [PUSH SI]
|
||||
* In which case, the stack variable flags are set
|
||||
****************************************************************************/
|
||||
Int Idiom1::checkStkVars (iICODE pIcode)
|
||||
{
|
||||
/* Look for PUSH SI */
|
||||
int si_matched=0;
|
||||
int di_matched=0;
|
||||
if(pIcode==m_end)
|
||||
return 0;
|
||||
if (pIcode->ic.ll.match(iPUSH,rSI))
|
||||
{
|
||||
si_matched = 1;
|
||||
++pIcode;
|
||||
if ((pIcode != m_end) && pIcode->ic.ll.match(iPUSH,rDI)) // Look for PUSH DI
|
||||
di_matched = 1;
|
||||
}
|
||||
else if (pIcode->ic.ll.match(iPUSH,rDI))
|
||||
{
|
||||
di_matched = 1;
|
||||
++pIcode;
|
||||
if ((pIcode != m_end) && pIcode->ic.ll.match(iPUSH,rSI)) // Look for PUSH SI
|
||||
si_matched = 1;
|
||||
}
|
||||
m_func->flg |= (si_matched ? SI_REGVAR : 0) | (di_matched ? DI_REGVAR : 0);
|
||||
return si_matched+di_matched;
|
||||
}
|
||||
bool Idiom1::match(iICODE picode)
|
||||
{
|
||||
uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */
|
||||
byte regi; /* register of the MOV */
|
||||
if(picode==m_end)
|
||||
return false;
|
||||
Int n;
|
||||
m_icodes.clear();
|
||||
m_min_off = 0;
|
||||
/* PUSH BP as first instruction of procedure */
|
||||
if ( !(picode->ic.ll.flg & I) && picode->ic.ll.src.regi == rBP)
|
||||
{
|
||||
m_icodes.push_back( picode++ ); // insert iPUSH
|
||||
if(picode==m_end)
|
||||
return false;
|
||||
/* MOV BP, SP as next instruction */
|
||||
if ( !picode->ic.ll.anyFlagSet(I | TARGET | CASE) && picode->ic.ll.match(iMOV ,rBP,rSP) )
|
||||
{
|
||||
m_icodes.push_back( picode++ ); // insert iMOV
|
||||
if(picode==m_end)
|
||||
return false;
|
||||
m_min_off = 2;
|
||||
|
||||
/* Look for SUB SP, immed */
|
||||
if (
|
||||
picode->ic.ll.anyFlagSet(I | TARGET | CASE) && picode->ic.ll.match(iSUB,rSP)
|
||||
)
|
||||
{
|
||||
m_icodes.push_back( picode++ ); // insert iSUB
|
||||
int n = checkStkVars (picode); // find iPUSH si [iPUSH di]
|
||||
for(int i=0; i<n; ++i)
|
||||
m_icodes.push_back(picode++); // insert
|
||||
}
|
||||
}
|
||||
|
||||
/* PUSH SI
|
||||
* [PUSH DI]
|
||||
* MOV BP, SP */
|
||||
else
|
||||
{
|
||||
int n = checkStkVars (picode);
|
||||
if (n > 0)
|
||||
{
|
||||
for(int i=0; i<n; ++i)
|
||||
m_icodes.push_back(picode++);
|
||||
if(picode == m_end)
|
||||
return false;
|
||||
/* Look for MOV BP, SP */
|
||||
if ( picode != m_end &&
|
||||
!picode->ic.ll.anyFlagSet(I | TARGET | CASE) &&
|
||||
picode->ic.ll.match(iMOV,rBP,rSP))
|
||||
{
|
||||
m_icodes.push_back(picode);
|
||||
m_min_off = 2 + (n * 2);
|
||||
}
|
||||
else
|
||||
return false; // Cristina: check this please!
|
||||
}
|
||||
else
|
||||
return false; // Cristina: check this please!
|
||||
}
|
||||
}
|
||||
else // push di [push si] / push si [push di]
|
||||
{
|
||||
n = checkStkVars (picode);
|
||||
for(int i=0; i<n; ++i)
|
||||
m_icodes.push_back(picode++);
|
||||
|
||||
}
|
||||
return !m_icodes.empty();
|
||||
}
|
||||
int Idiom1::action()
|
||||
{
|
||||
for(iICODE ic : m_icodes)
|
||||
{
|
||||
ic->invalidate();
|
||||
}
|
||||
m_func->flg |= PROC_IS_HLL;
|
||||
if(0!=m_min_off)
|
||||
m_func->args.m_minOff = m_min_off;
|
||||
return m_icodes.size();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user