dcc/src/idioms/xor_idioms.cpp
nemerle 9cd3226536 Normalize logic operation keywords and add use msvc fix
Logical or should be only 'or','and','not', and not error prone
'||','&&','!'
2016-04-25 11:39:07 +02:00

140 lines
4.2 KiB
C++

#include "xor_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
using namespace std;
/*****************************************************************************
* idiom21 - Assign long kte with high part zero
* XOR regH, regH
* MOV regL, kte
* => regH:regL = kte
* Eg: XOR dx, dx
* MOV ax, 3
* => dx:ax = 3
* Note: only the following valid combinations are available:
* dx:ax
* cx:bx
* Found in Borland Turbo C code.
****************************************************************************/
bool Idiom21::match (iICODE picode)
{
LLOperand *dst, *src;
if(distance(picode,m_end)<2)
return false;
m_icodes[0]=picode++;
m_icodes[1]=picode++;
if (not m_icodes[1]->ll()->testFlags(I))
return false;
dst = &m_icodes[0]->ll()->m_dst;
src = &m_icodes[0]->ll()->src();
if ((dst->regi == src->getReg2()) and (dst->getReg2() > 0) and (dst->getReg2() < INDEX_BX_SI))
{
if ((dst->getReg2() == rDX) and m_icodes[1]->ll()->match(rAX))
return true;
if ((dst->getReg2() == rCX) and m_icodes[1]->ll()->match(rBX))
return true;
}
return false;
}
int Idiom21::action()
{
Expr *rhs;
AstIdent *lhs;
lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0],HIGH_FIRST, m_icodes[0], eDEF, *m_icodes[1]->ll());
rhs = new Constant(m_icodes[1]->ll()->src().getImm2(), 4);
m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[0]->du.use.reset(); /* clear register used in iXOR */
m_icodes[1]->invalidate();
return 2;
}
/*****************************************************************************
* idiom7 - Assign zero
* XOR reg/stackOff, reg/stackOff
* Eg: XOR ax, ax
* => ax = 0
* Found in Borland Turbo C and Microsoft C code.
****************************************************************************/
bool Idiom7::match(iICODE picode)
{
if(picode==m_end)
return false;
const LLOperand *dst, *src;
m_icode=picode;
dst = &picode->ll()->m_dst;
src = &picode->ll()->src();
if (dst->regi == 0) /* global variable */
{
if ((dst->segValue == src->segValue) and (dst->off == src->off))
return true;
}
else if (dst->regi < INDEX_BX_SI) /* register */
{
if (dst->regi == src->regi)
return true;
}
else if ((dst->off) and (dst->seg == rSS) and (dst->regi == INDEX_BP)) /* offset from BP */
{
if ((dst->off == src->off) and (dst->seg == src->seg) and (dst->regi == src->regi))
return true;
}
return false;
}
int Idiom7::action()
{
Expr *lhs;
lhs = AstIdent::id (*m_icode->ll(), DST, m_func, m_icode, *m_icode, NONE);
m_icode->setAsgn(dynamic_cast<AstIdent *>(lhs), new Constant(0, 2));
m_icode->du.use.reset(); /* clear register used in iXOR */
m_icode->ll()->setFlags(I);
return 1;
}
/*****************************************************************************
* idiom10 - Jump if not equal to 0
* OR reg, reg
* JNE labX
* Eg: OR ax, ax
* JNE labX
* => CMP reg 0
* JNE labX
* This instruction is NOT converted into the equivalent high-level
* instruction "HLI_JCOND (reg != 0) labX" because we do not know yet if
* it forms part of a long register conditional test. It is therefore
* modified to simplify the analysis.
* Found in Borland Turbo C.
****************************************************************************/
bool Idiom10::match(iICODE pIcode)
{
if(distance(pIcode,m_end)<2)
return false;
m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++;
/* Check OR reg, reg */
if (not m_icodes[0]->ll()->testFlags(I) and
m_icodes[0]->ll()->src().isReg() and
(m_icodes[0]->ll()->src().getReg2() == m_icodes[0]->ll()->m_dst.getReg2()))
if (m_icodes[1]->ll()->match(iJNE)) //.conditionalJump()
{
return true;
}
return false;
}
int Idiom10::action()
{
m_icodes[0]->ll()->set(iCMP,I);
m_icodes[0]->ll()->replaceSrc(LLOperand::CreateImm2(0));
m_icodes[0]->du.def.reset(); //TODO: this defines FLAGS
m_icodes[0]->du1.clearAllDefs();
//m_icodes[0]->du1.numRegsDef = 0;
return 2;
}