317 lines
10 KiB
C++
317 lines
10 KiB
C++
#include "dcc.h"
|
|
#include "arith_idioms.h"
|
|
using namespace std;
|
|
|
|
/*****************************************************************************
|
|
* idiom5 - Long addition.
|
|
* ADD reg/stackOff, reg/stackOff
|
|
* ADC reg/stackOff, reg/stackOff
|
|
* Eg: ADD ax, [bp-4]
|
|
* ADC dx, [bp-2]
|
|
* => dx:ax = dx:ax + [bp-2]:[bp-4]
|
|
* Found in Borland Turbo C code.
|
|
* Commonly used idiom for long addition.
|
|
****************************************************************************/
|
|
bool Idiom5::match(iICODE pIcode)
|
|
{
|
|
if(distance(pIcode,m_end)<2)
|
|
return false;
|
|
m_icodes[0]=pIcode++;
|
|
m_icodes[1]=pIcode++;
|
|
if (m_icodes[1]->ll()->match(iADC))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
int Idiom5::action()
|
|
{
|
|
COND_EXPR *rhs,*lhs,*expr;
|
|
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
|
|
rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
|
|
expr = COND_EXPR::boolOp (lhs, rhs, ADD);
|
|
m_icodes[0]->setAsgn(lhs, expr);
|
|
m_icodes[1]->invalidate();
|
|
return 2;
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* idiom6 - Long substraction.
|
|
* SUB reg/stackOff, reg/stackOff
|
|
* SBB reg/stackOff, reg/stackOff
|
|
* Eg: SUB ax, [bp-4]
|
|
* SBB dx, [bp-2]
|
|
* => dx:ax = dx:ax - [bp-2]:[bp-4]
|
|
* Found in Borland Turbo C code.
|
|
* Commonly used idiom for long substraction.
|
|
****************************************************************************/
|
|
bool Idiom6::match(iICODE pIcode)
|
|
{
|
|
if(distance(pIcode,m_end)<2)
|
|
return false;
|
|
m_icodes[0]=pIcode++;
|
|
m_icodes[1]=pIcode++;
|
|
if (m_icodes[1]->ll()->match(iSBB))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
int Idiom6::action()
|
|
{
|
|
COND_EXPR *rhs,*lhs,*expr;
|
|
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
|
|
rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
|
|
expr = COND_EXPR::boolOp (lhs, rhs, SUB);
|
|
m_icodes[0]->setAsgn(lhs, expr);
|
|
m_icodes[1]->invalidate();
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* idiom 18: Post-increment or post-decrement in a conditional jump
|
|
* Used
|
|
* 0 MOV reg, var (including register variables)
|
|
* 1 INC var or DEC var <------------------------- input point
|
|
* 2 CMP var, Y
|
|
* 3 JX label
|
|
* => HLI_JCOND (var++ X Y)
|
|
* Eg: MOV ax, si
|
|
* INC si
|
|
* CMP ax, 8
|
|
* JL labX
|
|
* => HLI_JCOND (si++ < 8)
|
|
* Found in Borland Turbo C. Intrinsic to C languages.
|
|
****************************************************************************/
|
|
bool Idiom18::match(iICODE picode)
|
|
{
|
|
if(picode==m_func->Icode.begin())
|
|
return false;
|
|
if(std::distance(picode,m_end)<3)
|
|
return false;
|
|
--picode; //
|
|
|
|
for(int i=0; i<4; ++i)
|
|
m_icodes[i] =picode++;
|
|
|
|
m_is_dec = m_icodes[1]->ll()->match(iDEC);
|
|
int type = -1; /* type of variable: 1 = reg-var, 2 = local */
|
|
uint8_t regi; /* register of the MOV */
|
|
|
|
/* Get variable */
|
|
if (m_icodes[1]->ll()->dst.regi == 0) /* global variable */
|
|
{
|
|
/* not supported yet */
|
|
type = 0;
|
|
}
|
|
else if ( m_icodes[1]->ll()->dst.isReg() ) /* register */
|
|
{
|
|
if ((m_icodes[1]->ll()->dst.regi == rSI) && (m_func->flg & SI_REGVAR))
|
|
type = 1;
|
|
else if ((m_icodes[1]->ll()->dst.regi == rDI) && (m_func->flg & DI_REGVAR))
|
|
type = 1;
|
|
}
|
|
else if (m_icodes[1]->ll()->dst.off) /* local variable */
|
|
type = 2;
|
|
else /* indexed */
|
|
{
|
|
type=3;
|
|
/* not supported yet */
|
|
printf("Unsupported idiom18 type: indexed");
|
|
}
|
|
|
|
switch(type)
|
|
{
|
|
case 0: // global
|
|
printf("Unsupported idiom18 type: global variable");
|
|
break;
|
|
case 1: /* register variable */
|
|
/* Check previous instruction for a MOV */
|
|
if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().regi == m_icodes[1]->ll()->dst.regi))
|
|
{
|
|
regi = m_icodes[0]->ll()->dst.regi;
|
|
if ( m_icodes[0]->ll()->dst.isReg() )
|
|
{
|
|
if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) &&
|
|
m_icodes[3]->ll()->conditionalJump() )
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
case 2: /* local */
|
|
if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().off == m_icodes[1]->ll()->dst.off))
|
|
{
|
|
regi = m_icodes[0]->ll()->dst.regi;
|
|
if ( m_icodes[0]->ll()->dst.isReg() )
|
|
{
|
|
if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) &&
|
|
m_icodes[3]->ll()->conditionalJump() )
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
case 3: // indexed
|
|
printf("Unsupported idiom18 type: indexed");
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int Idiom18::action() // action length
|
|
{
|
|
COND_EXPR *rhs, *lhs; /* Pointers to left and right hand side exps */
|
|
COND_EXPR *expr;
|
|
lhs = COND_EXPR::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[1], *m_icodes[1], eUSE);
|
|
lhs = COND_EXPR::unary ( m_is_dec ? POST_DEC : POST_INC, lhs);
|
|
rhs = COND_EXPR::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[1], *m_icodes[3], eUSE);
|
|
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]);
|
|
m_icodes[3]->setJCond(expr);
|
|
|
|
m_icodes[0]->invalidate();
|
|
m_icodes[1]->invalidate();
|
|
m_icodes[2]->invalidate();
|
|
return 3;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* idiom 19: pre-increment or pre-decrement in conditional jump, comparing against 0.
|
|
* [INC | DEC] var (including register vars)
|
|
* JX lab JX lab
|
|
* => HLI_JCOND (++var X 0) or HLI_JCOND (--var X 0)
|
|
* Eg: INC [bp+4]
|
|
* JG lab2
|
|
* => HLI_JCOND (++[bp+4] > 0)
|
|
* Found in Borland Turbo C. Intrinsic to C language.
|
|
****************************************************************************/
|
|
bool Idiom19::match(iICODE picode)
|
|
{
|
|
if(std::distance(picode,m_end)<2)
|
|
return false;
|
|
|
|
for(int i=0; i<2; ++i)
|
|
m_icodes[i] =picode++;
|
|
m_is_dec = m_icodes[0]->ll()->match(iDEC);
|
|
if (m_icodes[0]->ll()->dst.regi == 0) /* global variable */
|
|
/* not supported yet */ ;
|
|
else if ( m_icodes[0]->ll()->dst.isReg() ) /* register */
|
|
{
|
|
// if (((picode->ll()->dst.regi == rSI) && (pproc->flg & SI_REGVAR)) ||
|
|
// ((picode->ll()->dst.regi == rDI) && (pproc->flg & DI_REGVAR)))
|
|
if (m_icodes[1]->ll()->conditionalJump())
|
|
return true;
|
|
}
|
|
else if (m_icodes[0]->ll()->dst.off) /* stack variable */
|
|
{
|
|
if ( m_icodes[1]->ll()->conditionalJump() )
|
|
return true;
|
|
}
|
|
else /* indexed */
|
|
{
|
|
/* not supported yet */
|
|
}
|
|
return false;
|
|
}
|
|
int Idiom19::action()
|
|
{
|
|
COND_EXPR *lhs,*rhs,*expr;
|
|
lhs = COND_EXPR::id (*m_icodes[1]->ll(), DST, m_func, m_icodes[0], *m_icodes[1], eUSE);
|
|
lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
|
|
rhs = COND_EXPR::idKte (0, 2);
|
|
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[1]->ll()->getOpcode() - iJB]);
|
|
m_icodes[1]->setJCond(expr);
|
|
m_icodes[0]->invalidate();
|
|
return 2;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* idiom20: Pre increment/decrement in conditional expression (compares
|
|
* against a register, variable or constant different than 0).
|
|
* INC var or DEC var (including register vars)
|
|
* MOV reg, var MOV reg, var
|
|
* CMP reg, Y CMP reg, Y
|
|
* JX lab JX lab
|
|
* => HLI_JCOND (++var X Y) or HLI_JCOND (--var X Y)
|
|
* Eg: INC si (si is a register variable)
|
|
* MOV ax, si
|
|
* CMP ax, 2
|
|
* JL lab4
|
|
* => HLI_JCOND (++si < 2)
|
|
* Found in Turbo C. Intrinsic to C language.
|
|
****************************************************************************/
|
|
bool Idiom20::match(iICODE picode)
|
|
{
|
|
uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */
|
|
uint8_t regi; /* register of the MOV */
|
|
if(std::distance(picode,m_end)<4)
|
|
return false;
|
|
for(int i=0; i<4; ++i)
|
|
m_icodes[i] =picode++;
|
|
|
|
m_is_dec = m_icodes[0]->ll()->match(iDEC);
|
|
|
|
LLOperand &ll_dest(m_icodes[0]->ll()->dst);
|
|
/* Get variable */
|
|
if (ll_dest.regi == 0) /* global variable */
|
|
{
|
|
/* not supported yet */ ;
|
|
}
|
|
else if ( ll_dest.isReg() ) /* register */
|
|
{
|
|
if ((ll_dest.regi == rSI) && (m_func->flg & SI_REGVAR))
|
|
type = 1;
|
|
else if ((ll_dest.regi == rDI) && (m_func->flg & DI_REGVAR))
|
|
type = 1;
|
|
}
|
|
else if (ll_dest.off) /* local variable */
|
|
type = 2;
|
|
else /* indexed */
|
|
{
|
|
printf("idiom20 : Unsupported type [indexed]\n");
|
|
/* not supported yet */ ;
|
|
}
|
|
|
|
/* Check previous instruction for a MOV */
|
|
if (type == 1) /* register variable */
|
|
{
|
|
if (m_icodes[1]->ll()->match(iMOV) &&
|
|
(m_icodes[1]->ll()->src().regi == ll_dest.regi))
|
|
{
|
|
regi = m_icodes[1]->ll()->dst.regi;
|
|
if ( m_icodes[1]->ll()->dst.isReg() )
|
|
{
|
|
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) &&
|
|
m_icodes[3]->ll()->conditionalJump())
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
else if (type == 2) /* local */
|
|
{
|
|
if ( m_icodes[0]->ll()->match(iMOV) &&
|
|
(m_icodes[1]->ll()->src().off == ll_dest.off))
|
|
{
|
|
regi = m_icodes[1]->ll()->dst.regi;
|
|
if ( m_icodes[1]->ll()->dst.isReg() )
|
|
{
|
|
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) &&
|
|
m_icodes[3]->ll()->conditionalJump())
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
int Idiom20::action()
|
|
{
|
|
COND_EXPR *lhs,*rhs,*expr;
|
|
lhs = COND_EXPR::id (*m_icodes[1]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], eUSE);
|
|
lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
|
|
rhs = COND_EXPR::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[0], *m_icodes[3], eUSE);
|
|
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]);
|
|
m_icodes[3]->setJCond(expr);
|
|
for(int i=0; i<3; ++i)
|
|
m_icodes[i]->invalidate();
|
|
return 4;
|
|
}
|