dcc/src/idioms/neg_idioms.cpp
2012-03-08 21:47:59 +01:00

103 lines
3.1 KiB
C++

#include "dcc.h"
#include "neg_idioms.h"
using namespace std;
/*****************************************************************************
* idiom11 - Negate long integer
* NEG regH
* NEG regL
* SBB regH, 0
* Eg: NEG dx
* NEG ax
* SBB dx, 0
* => dx:ax = - dx:ax
* Found in Borland Turbo C.
****************************************************************************/
bool Idiom11::match (iICODE picode)
{
const char *matchstring="(oNEG rH) (oNEG rL) (SBB \rH i0)";
condId type; /* type of argument */
if(distance(picode,m_end)<3)
return false;
for(int i=0; i<3; ++i)
m_icodes[i]=picode++;
type = m_icodes[0]->idType(DST);
if(type==CONSTANT || type == OTHER)
return false;
/* Check NEG reg/mem
* SBB reg/mem, 0*/
if (not m_icodes[1]->ll()->match(iNEG) or not m_icodes[2]->ll()->match(iSBB))
return false;
switch (type)
{
case GLOB_VAR:
if ((m_icodes[2]->ll()->dst.segValue == m_icodes[0]->ll()->dst.segValue) &&
(m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off))
return true;
break;
case REGISTER:
if (m_icodes[2]->ll()->dst.regi == m_icodes[0]->ll()->dst.regi)
return true;
break;
case PARAM:
case LOCAL_VAR:
if (m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off)
return true;
break;
}
return false;
}
int Idiom11::action()
{
COND_EXPR *lhs,*rhs;
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], HIGH_FIRST,m_icodes[0], USE_DEF, m_icodes[1]);
rhs = COND_EXPR::unary (NEGATION, lhs);
m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[1]->invalidate();
m_icodes[2]->invalidate();
return 3;
}
/*****************************************************************************
* idiom 16: Bitwise negation
* NEG reg
* SBB reg, reg
* INC reg
* => ASGN reg, !reg
* Eg: NEG ax
* SBB ax, ax
* INC ax
* => ax = !ax
* Found in Borland Turbo C when negating bitwise.
****************************************************************************/
bool Idiom16::match (iICODE picode)
{
const char *matchstring="(oNEG rR) (oSBB rR rR) (oINC rR)";
if(distance(picode,m_end)<3)
return false;
for(int i=0; i<3; ++i)
m_icodes[i]=picode++;
uint8_t regi = m_icodes[0]->ll()->dst.regi;
if ((regi >= rAX) && (regi < INDEX_BX_SI))
{
if (m_icodes[1]->ll()->match(iSBB) && m_icodes[2]->ll()->match(iINC))
if ((m_icodes[1]->ll()->dst.regi == (m_icodes[1]->ll()->src.regi)) &&
m_icodes[1]->ll()->match((eReg)regi) &&
m_icodes[2]->ll()->match((eReg)regi))
return true;
}
return false;
}
int Idiom16::action()
{
COND_EXPR *lhs,*rhs;
lhs = COND_EXPR::idReg (m_icodes[0]->ll()->dst.regi, m_icodes[0]->ll()->getFlag(),&m_func->localId);
rhs = COND_EXPR::unary (NEGATION, lhs->clone());
m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[1]->invalidate();
m_icodes[2]->invalidate();
return 3;
}