fixed refactoring bugs

This commit is contained in:
Artur K 2012-02-27 21:26:54 +01:00
parent 11ae65efba
commit 777a260300
17 changed files with 1655 additions and 0 deletions

View File

@ -0,0 +1,75 @@
#pragma once
#include <vector>
#include "idiom.h"
#include "icode.h"
#include <deque>
struct Idiom5 : public Idiom
{
protected:
iICODE m_icodes[2];
public:
virtual ~Idiom5() {}
Idiom5(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 2;}
bool match(iICODE pIcode);
int action();
};
struct Idiom6 : public Idiom
{
protected:
iICODE m_icodes[2];
public:
virtual ~Idiom6() {}
Idiom6(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 2;}
bool match(iICODE pIcode);
int action();
};
struct Idiom18 : public Idiom
{
protected:
iICODE m_icodes[4];
bool m_is_dec;
public:
Idiom18(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 4;}
bool match(iICODE picode);
int action();
};
struct Idiom19 : public Idiom
{
protected:
iICODE m_icodes[2];
bool m_is_dec;
public:
Idiom19(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 2;}
bool match(iICODE picode);
int action();
};
struct Idiom20 : public Idiom
{
protected:
iICODE m_icodes[4];
bool m_is_dec;
public:
Idiom20(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 4;}
bool match(iICODE picode);
int action();
};

View File

@ -0,0 +1,42 @@
#pragma once
#include <vector>
#include "idiom.h"
#include "icode.h"
#include <deque>
struct CallIdiom : public Idiom
{
protected:
int m_param_count;
public:
virtual ~CallIdiom() {}
CallIdiom(Function *f) : Idiom(f)
{
}
};
struct Idiom3 : public CallIdiom
{
protected:
iICODE m_icodes[2];
public:
virtual ~Idiom3() {}
Idiom3(Function *f) : CallIdiom(f)
{
}
uint8_t minimum_match_length() {return 2;}
bool match(iICODE pIcode);
int action();
};
struct Idiom17 : public CallIdiom
{
protected:
std::vector<iICODE> m_icodes;
public:
virtual ~Idiom17() {}
Idiom17(Function *f) : CallIdiom(f)
{
}
uint8_t minimum_match_length() {return 2;}
bool match(iICODE pIcode);
int action();
};

View 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();
};

22
include/idioms/idiom.h Normal file
View File

@ -0,0 +1,22 @@
#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;
virtual int action()=0;
int operator ()(iICODE at)
{
if(match(at))
return action();
return 1;
}
};

17
include/idioms/idiom1.h Normal file
View File

@ -0,0 +1,17 @@
#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();
size_t match_length() {return m_icodes.size();}
};

View File

@ -0,0 +1,36 @@
#pragma once
#include <vector>
#include "idiom.h"
#include "icode.h"
#include <deque>
struct Idiom14 : public Idiom
{
protected:
iICODE m_icodes[2];
byte m_regL;
byte m_regH;
public:
virtual ~Idiom14() {}
Idiom14(Function *f) : Idiom(f),m_regL(0),m_regH(0)
{
}
uint8_t minimum_match_length() {return 2;}
bool match(iICODE pIcode);
int action();
};
struct Idiom13 : public Idiom
{
protected:
iICODE m_icodes[2];
byte m_loaded_reg;
public:
virtual ~Idiom13() {}
Idiom13(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 2;}
bool match(iICODE pIcode);
int action();
};

View File

@ -0,0 +1,33 @@
#pragma once
#include <vector>
#include "idiom.h"
#include "icode.h"
#include <deque>
struct Idiom11 : public Idiom
{
protected:
iICODE m_icodes[3];
public:
virtual ~Idiom11() {}
Idiom11(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 3;}
bool match(iICODE pIcode);
int action();
};
struct Idiom16 : public Idiom
{
protected:
iICODE m_icodes[3];
public:
virtual ~Idiom16() {}
Idiom16(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 3;}
bool match(iICODE pIcode);
int action();
};

View File

@ -0,0 +1,66 @@
#pragma once
#include <vector>
#include "idiom.h"
#include "icode.h"
#include <deque>
struct Idiom8 : public Idiom
{
protected:
iICODE m_icodes[2];
byte m_loaded_reg;
public:
virtual ~Idiom8() {}
Idiom8(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 2;}
bool match(iICODE pIcode);
int action();
};
struct Idiom15 : public Idiom
{
protected:
std::vector<iICODE> m_icodes;
public:
virtual ~Idiom15() {}
Idiom15(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 2;}
bool match(iICODE pIcode);
int action();
};
struct Idiom12 : public Idiom
{
protected:
iICODE m_icodes[2];
byte m_loaded_reg;
public:
virtual ~Idiom12() {}
Idiom12(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 2;}
bool match(iICODE pIcode);
int action();
};
struct Idiom9 : public Idiom
{
protected:
iICODE m_icodes[2];
byte m_loaded_reg;
public:
virtual ~Idiom9() {}
Idiom9(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 2;}
bool match(iICODE pIcode);
int action();
};

View File

@ -0,0 +1,46 @@
#pragma once
#include <vector>
#include "idiom.h"
#include "icode.h"
#include <deque>
struct Idiom21 : public Idiom
{
protected:
iICODE m_icodes[2];
public:
virtual ~Idiom21() {}
Idiom21(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 2;}
bool match(iICODE pIcode);
int action();
};
struct Idiom7 : public Idiom
{
protected:
iICODE m_icode;
public:
virtual ~Idiom7() {}
Idiom7(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 1;}
bool match(iICODE pIcode);
int action();
};
struct Idiom10 : public Idiom
{
protected:
iICODE m_icodes[2];
public:
virtual ~Idiom10() {}
Idiom10(Function *f) : Idiom(f)
{
}
uint8_t minimum_match_length() {return 1;}
bool match(iICODE pIcode);
int action();
};

327
src/idioms/arith_idioms.cpp Normal file
View File

@ -0,0 +1,327 @@
#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]->ic.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, 1);
rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, 1);
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]->ic.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, 1);
rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, 1);
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(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]->ic.ll.match(iDEC);
int type = -1; /* type of variable: 1 = reg-var, 2 = local */
byte regi; /* register of the MOV */
/* Get variable */
if (m_icodes[1]->ic.ll.dst.regi == 0) /* global variable */
{
/* not supported yet */
type = 0;
}
else if (m_icodes[1]->ic.ll.dst.regi < INDEXBASE) /* register */
{
if ((m_icodes[1]->ic.ll.dst.regi == rSI) && (m_func->flg & SI_REGVAR))
type = 1;
else if ((m_icodes[1]->ic.ll.dst.regi == rDI) && (m_func->flg & DI_REGVAR))
type = 1;
}
else if (m_icodes[1]->ic.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]->ic.ll.match(iMOV) && (m_icodes[0]->ic.ll.src.regi == m_icodes[1]->ic.ll.dst.regi))
{
regi = m_icodes[0]->ic.ll.dst.regi;
if ((regi > 0) && (regi < INDEXBASE))
{
if ( m_icodes[2]->ic.ll.match(iCMP) && (m_icodes[2]->ic.ll.dst.regi == regi) &&
m_icodes[3]->ic.ll.conditionalJump() )
return true;
}
}
break;
case 2: /* local */
if (m_icodes[0]->ic.ll.match(iMOV) && (m_icodes[0]->ic.ll.src.off == m_icodes[1]->ic.ll.dst.off))
{
regi = m_icodes[0]->ic.ll.dst.regi;
if ((regi > 0) && (regi < INDEXBASE))
{
if ( m_icodes[2]->ic.ll.match(iCMP) && (m_icodes[2]->ic.ll.dst.regi == regi) &&
m_icodes[3]->ic.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], 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], SRC, m_func, m_icodes[1], *m_icodes[3], eUSE);
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ic.ll.opcode - iJB]);
m_icodes[3]->setJCond(expr);
m_icodes[0]->invalidate();
m_icodes[1]->invalidate();
m_icodes[2]->invalidate();
return 3;
/*
lhs = COND_EXPR::id (*(pIcode-1), SRC, this, pIcode, *pIcode, eUSE);
if (pIcode->ic.ll.opcode == iDEC)
lhs = COND_EXPR::unary (POST_DEC, lhs);
else
lhs = COND_EXPR::unary (POST_INC, lhs);
rhs = COND_EXPR::id (*(pIcode+1), SRC, this, pIcode, *(pIcode+2), eUSE);
exp = COND_EXPR::boolOp (lhs, rhs, condOpJCond[(pIcode+2)->ic.ll.opcode - iJB]);
(pIcode+2)->setJCond(exp);
(pIcode-1)->invalidate();
pIcode->invalidate();
(pIcode+1)->invalidate();
pIcode += 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]->ic.ll.match(iDEC);
if (m_icodes[0]->ic.ll.dst.regi == 0) /* global variable */
/* not supported yet */ ;
else if (m_icodes[0]->ic.ll.dst.regi < INDEXBASE) /* register */
{
// if (((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR)) ||
// ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR)))
if (m_icodes[1]->ic.ll.conditionalJump())
return true;
}
else if (m_icodes[0]->ic.ll.dst.off) /* stack variable */
{
if ( m_icodes[1]->ic.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], 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]->ic.ll.opcode - 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 */
byte 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]->ic.ll.match(iDEC);
/* Get variable */
if (m_icodes[0]->ic.ll.dst.regi == 0) /* global variable */
{
/* not supported yet */ ;
}
else if (m_icodes[0]->ic.ll.dst.regi < INDEXBASE) /* register */
{
if ((m_icodes[0]->ic.ll.dst.regi == rSI) && (m_func->flg & SI_REGVAR))
type = 1;
else if ((m_icodes[0]->ic.ll.dst.regi == rDI) && (m_func->flg & DI_REGVAR))
type = 1;
}
else if (m_icodes[0]->ic.ll.dst.off) /* local variable */
type = 2;
else /* indexed */
{
printf("idiom20 : Unsupported type\n");
/* not supported yet */ ;
}
/* Check previous instruction for a MOV */
if (type == 1) /* register variable */
{
if (m_icodes[1]->ic.ll.match(iMOV) &&
(m_icodes[1]->ic.ll.src.regi == m_icodes[0]->ic.ll.dst.regi))
{
regi = m_icodes[1]->ic.ll.dst.regi;
if ((regi > 0) && (regi < INDEXBASE))
{
if (m_icodes[2]->ic.ll.match(iCMP,(eReg)regi) &&
m_icodes[3]->ic.ll.conditionalJump())
return true;
}
}
}
else if (type == 2) /* local */
{
if ( m_icodes[0]->ic.ll.match(iMOV) &&
(m_icodes[1]->ic.ll.src.off == m_icodes[0]->ic.ll.dst.off))
{
regi = m_icodes[1]->ic.ll.dst.regi;
if ((regi > 0) && (regi < INDEXBASE))
{
if (m_icodes[2]->ic.ll.match(iCMP,(eReg)regi) &&
m_icodes[3]->ic.ll.conditionalJump())
return true;
}
}
}
return false;
}
int Idiom20::action()
{
COND_EXPR *lhs,*rhs,*expr;
lhs = COND_EXPR::id (*m_icodes[1], 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], SRC, m_func, m_icodes[0], *m_icodes[3], eUSE);
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ic.ll.opcode - iJB]);
m_icodes[3]->setJCond(expr);
m_icodes[0]->invalidate();
m_icodes[1]->invalidate();
m_icodes[2]->invalidate();
return 4;
}

115
src/idioms/call_idioms.cpp Normal file
View File

@ -0,0 +1,115 @@
#include "dcc.h"
#include "call_idioms.h"
using namespace std;
/*****************************************************************************
* idiom3 - C calling convention.
* CALL(F) proc_X
* ADD SP, immed
* Eg: CALL proc_X
* ADD SP, 6
* => pProc->cbParam = immed
* Special case: when the call is at the end of the procedure,
* sometimes the stack gets restored by a MOV sp, bp.
* Need to flag the procedure in these cases.
* Used by compilers to restore the stack when invoking a procedure using
* the C calling convention.
****************************************************************************/
bool Idiom3::match(iICODE picode)
{
if(distance(picode,m_end)<2)
return false;
m_param_count=0;
/* Match ADD SP, immed */
for(int i=0; i<2; ++i)
m_icodes[i] = picode++;
if ( (m_icodes[1]->ic.ll.flg & I) && m_icodes[1]->ic.ll.match(iADD,rSP))
{
m_param_count = m_icodes[1]->ic.ll.src.op();
return true;
}
else if (m_icodes[1]->ic.ll.match(iMOV,rSP,rBP))
{
m_icodes[0]->ic.ll.flg |= REST_STK;
return true;
}
return 0;
}
int Idiom3::action()
{
if (m_icodes[0]->ic.ll.flg & I)
{
m_icodes[0]->ic.ll.src.proc.proc->cbParam = (int16)m_param_count;
m_icodes[0]->ic.ll.src.proc.cb = m_param_count;
m_icodes[0]->ic.ll.src.proc.proc->flg |= CALL_C;
}
else
{
printf("Indirect call at idiom3\n");
}
m_icodes[1]->invalidate();
return 2;
}
/*****************************************************************************
* idiom 17 - C calling convention.
* CALL(F) xxxx
* POP reg
* [POP reg] reg in {AX, BX, CX, DX}
* Eg: CALL proc_X
* POP cx
* POP cx (4 bytes of arguments)
* => pProc->cbParam = # pops * 2
* Found in Turbo C when restoring the stack for a procedure that uses the
* C calling convention. Used to restore the stack of 2 or 4 bytes args.
****************************************************************************/
bool Idiom17::match(iICODE picode)
{
if(distance(picode,m_end)<2)
return false;
m_param_count=0; /* Count on # pops */
m_icodes.clear();
/* Match ADD SP, immed */
for(int i=0; i<2; ++i)
m_icodes.push_back(picode++);
byte regi;
/* Match POP reg */
if (m_icodes[1]->ic.ll.match(iPOP))
{
int i=0;
regi = m_icodes[1]->ic.ll.dst.regi;
if ((regi >= rAX) && (regi <= rBX))
i++;
while (picode != m_end && picode->ic.ll.match(iPOP))
{
if (picode->ic.ll.dst.regi != regi)
break;
i++;
m_icodes.push_back(picode++);
}
m_param_count = i*2;
}
return m_param_count!=0;
}
int Idiom17::action()
{
if (m_icodes[0]->isLlFlag(I))
{
m_icodes[0]->ic.ll.src.proc.proc->cbParam = (int16)m_param_count;
m_icodes[0]->ic.ll.src.proc.cb = m_param_count;
m_icodes[0]->ic.ll.src.proc.proc->flg |= CALL_C;
for(int idx=1; idx<m_icodes.size(); ++idx)
{
m_icodes[idx]->invalidate();
}
}
// TODO : it's a calculated call
else
{
printf("Indirect call at idiom17\n");
}
return m_icodes.size();
}

View 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 1;
}

137
src/idioms/idiom1.cpp Normal file
View File

@ -0,0 +1,137 @@
#include "idiom1.h"
#include "dcc.h"
/*****************************************************************************
/* 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;
}
/*****************************************************************************
* 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]
****************************************************************************/
bool Idiom1::match(iICODE picode)
{
uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */
byte regi; /* register of the MOV */
if(m_func->flg & PROC_HLL)
return false;
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_HLL;
if(0!=m_min_off)
{
m_func->args.m_minOff = m_min_off;
m_func->flg |= PROC_IS_HLL;
}
return m_icodes.size();
}

110
src/idioms/mov_idioms.cpp Normal file
View File

@ -0,0 +1,110 @@
#include "dcc.h"
#include "mov_idioms.h"
using namespace std;
/*****************************************************************************
* idiom 14 - Long word assign
* MOV regL, mem/reg
* XOR regH, regH
* Eg: MOV ax, di
* XOR dx, dx
* => MOV dx:ax, di
* Note: only the following combinations are allowed:
* dx:ax
* cx:bx
* this is to remove the possibility of making errors in situations
* like this:
* MOV dx, offH
* MOV ax, offL
* XOR cx, cx
* Found in Borland Turbo C, used for division of unsigned integer
* operands.
****************************************************************************/
bool Idiom14::match(iICODE pIcode)
{
if(distance(pIcode,m_end)<2)
return false;
m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++;
/* Check for regL */
m_regL = m_icodes[0]->ic.ll.dst.regi;
if (not m_icodes[0]->isLlFlag(I) && ((m_regL == rAX) || (m_regL ==rBX)))
{
/* Check for XOR regH, regH */
if (m_icodes[1]->ic.ll.match(iXOR) && not m_icodes[1]->isLlFlag(I))
{
m_regH = m_icodes[1]->ic.ll.dst.regi;
if (m_regH == m_icodes[1]->ic.ll.src.regi)
{
if ((m_regL == rAX) && (m_regH == rDX))
return true;
if ((m_regL == rBX) && (m_regH == rCX))
return true;
}
}
}
return false;
}
int Idiom14::action()
{
int idx;
COND_EXPR *lhs,*rhs;
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, m_regH, m_regL, m_icodes[0]);
lhs = COND_EXPR::idLongIdx (idx);
m_icodes[0]->setRegDU( m_regH, eDEF);
rhs = COND_EXPR::id (*m_icodes[0], SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[1]->invalidate();
return 2;
}
/*****************************************************************************
* idiom 13 - Word assign
* MOV regL, mem
* MOV regH, 0
* Eg: MOV al, [bp-2]
* MOV ah, 0
* => MOV ax, [bp-2]
* Found in Borland Turbo C, used for multiplication and division of
* byte operands (ie. they need to be extended to words).
****************************************************************************/
bool Idiom13::match(iICODE pIcode)
{
if(distance(pIcode,m_end)<2)
return false;
m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++;
m_loaded_reg = 0;
byte regi;
/* Check for regL */
regi = m_icodes[0]->ic.ll.dst.regi;
if (not m_icodes[0]->isLlFlag(I) && (regi >= rAL) && (regi <= rBH))
{
/* Check for MOV regH, 0 */
if (m_icodes[1]->ic.ll.match(iMOV) && m_icodes[1]->isLlFlag(I) && (m_icodes[1]->ic.ll.src.op() == 0))
{
if (m_icodes[1]->ic.ll.dst.regi == (regi + 4)) //TODO: based on distance between AH-AL,BH-BL etc.
{
m_loaded_reg=(regi - rAL + rAX);
return true;
}
}
}
return false;
}
int Idiom13::action()
{
COND_EXPR *lhs,*rhs;
lhs = COND_EXPR::idReg (m_loaded_reg, 0, &m_func->localId);
m_icodes[0]->setRegDU( m_loaded_reg, eDEF);
m_icodes[0]->du1.numRegsDef--; /* prev byte reg def */
rhs = COND_EXPR::id (*m_icodes[0], SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[1]->invalidate();
return 2;
}

102
src/idioms/neg_idioms.cpp Normal file
View File

@ -0,0 +1,102 @@
#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]->ic.ll.match(iNEG) or not m_icodes[2]->ic.ll.match(iSBB))
return false;
switch (type)
{
case GLOB_VAR:
if ((m_icodes[2]->ic.ll.dst.segValue == m_icodes[0]->ic.ll.dst.segValue) &&
(m_icodes[2]->ic.ll.dst.off == m_icodes[0]->ic.ll.dst.off))
return true;
break;
case REGISTER:
if (m_icodes[2]->ic.ll.dst.regi == m_icodes[0]->ic.ll.dst.regi)
return true;
break;
case PARAM:
case LOCAL_VAR:
if (m_icodes[2]->ic.ll.dst.off == m_icodes[0]->ic.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, 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++;
byte regi = m_icodes[0]->ic.ll.dst.regi;
if ((regi >= rAX) && (regi < INDEXBASE))
{
if (m_icodes[1]->ic.ll.match(iSBB) && m_icodes[2]->ic.ll.match(iINC))
if ((m_icodes[1]->ic.ll.dst.regi == (m_icodes[1]->ic.ll.src.regi)) &&
m_icodes[1]->ic.ll.match((eReg)regi) &&
m_icodes[2]->ic.ll.match((eReg)regi))
return true;
}
return false;
}
int Idiom16::action()
{
COND_EXPR *lhs,*rhs;
lhs = COND_EXPR::idReg (m_icodes[0]->ic.ll.dst.regi, m_icodes[0]->ic.ll.flg,&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;
}

176
src/idioms/shift_idioms.cpp Normal file
View File

@ -0,0 +1,176 @@
#include "dcc.h"
#include "shift_idioms.h"
using namespace std;
/*****************************************************************************
* idiom8 - Shift right by 1 (signed long ops)
* SAR reg, 1
* RCR reg, 1
* Eg: SAR dx, 1
* RCR ax, 1
* => dx:ax = dx:ax >> 1 (dx:ax are signed long)
* Found in Microsoft C code for long signed variable shift right.
****************************************************************************/
bool Idiom8::match(iICODE pIcode)
{
if(distance(pIcode,m_end)<2)
return false;
m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++;
if (m_icodes[0]->isLlFlag(I) && (m_icodes[0]->ic.ll.src.op() == 1))
if (m_icodes[1]->ic.ll.match(iRCR) &&
m_icodes[1]->isLlFlag(I) &&
(m_icodes[1]->ic.ll.src.op() == 1))
return true;
return false;
}
int Idiom8::action()
{
int idx;
COND_EXPR *rhs,*lhs,*expr;
byte regH,regL;
regH=m_icodes[0]->ic.ll.dst.regi;
regL=m_icodes[1]->ic.ll.dst.regi;
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, regH, regL, m_icodes[0]);
lhs = COND_EXPR::idLongIdx (idx);
m_icodes[0]->setRegDU( regL, USE_DEF);
rhs = COND_EXPR::idKte(1,2);
expr = COND_EXPR::boolOp(lhs, rhs, SHR);
m_icodes[0]->setAsgn(lhs, expr);
m_icodes[1]->invalidate();
return 2;
}
/*****************************************************************************
* idiom 15 - Shift left by n
* SHL reg, 1
* SHL reg, 1
* [...]
* [SHL reg, 1]
* Eg: SHL ax, 1
* SHL ax, 1
* => ax = ax << 2
* Found in Borland Turbo C code to index an array (array multiplication)
****************************************************************************/
bool Idiom15::match(iICODE pIcode)
{
Int n = 1;
byte regi;
if(distance(pIcode,m_end)<2)
return false;
/* Match SHL reg, 1 */
if (not pIcode->isLlFlag(I) or (pIcode->ic.ll.src.op() != 1))
return false;
m_icodes.clear();
regi = pIcode->ic.ll.dst.regi;
m_icodes.push_back(pIcode++);
while( (pIcode!=m_end) and
pIcode->ic.ll.match(iSHL,(eReg)regi) and
pIcode->isLlFlag(I) and
(pIcode->ic.ll.src.op() == 1) )
{
n++;
m_icodes.push_back(pIcode++);
}
return m_icodes.size()>1;
}
int Idiom15::action()
{
COND_EXPR *lhs,*rhs,*exp;
lhs = COND_EXPR::idReg (m_icodes[0]->ic.ll.dst.regi,
m_icodes[0]->ic.ll.flg & NO_SRC_B,
&m_func->localId);
rhs = COND_EXPR::idKte (m_icodes.size(), 2);
exp = COND_EXPR::boolOp (lhs, rhs, SHL);
m_icodes[0]->setAsgn(lhs, exp);
for (size_t i=1; i<m_icodes.size()-1; ++i)
{
m_icodes[i]->invalidate();
}
return m_icodes.size();
}
/*****************************************************************************
* idiom12 - Shift left long by 1
* SHL reg, 1
* RCL reg, 1
* Eg: SHL ax, 1
* RCL dx, 1
* => dx:ax = dx:ax << 1
* Found in Borland Turbo C code for long variable shift left.
****************************************************************************/
bool Idiom12::match(iICODE pIcode)
{
if(distance(pIcode,m_end)<2)
return false;
m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++;
if (m_icodes[0]->isLlFlag(I) && (m_icodes[0]->ic.ll.src.op() == 1))
if (m_icodes[1]->ic.ll.match(iRCL) &&
m_icodes[1]->isLlFlag(I) && (m_icodes[1]->ic.ll.src.op() == 1))
return true;
return false;
}
int Idiom12::action()
{
int idx;
COND_EXPR *rhs,*lhs,*expr;
byte regH,regL;
regL=m_icodes[0]->ic.ll.dst.regi;
regH=m_icodes[1]->ic.ll.dst.regi;
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN, regH, regL,m_icodes[0]);
lhs = COND_EXPR::idLongIdx (idx);
m_icodes[0]->setRegDU( regH, USE_DEF);
rhs = COND_EXPR::idKte (1, 2);
expr = COND_EXPR::boolOp (lhs, rhs, SHL);
m_icodes[0]->setAsgn(lhs, expr);
m_icodes[1]->invalidate();
return 2;
}
/*****************************************************************************
* idiom9 - Shift right by 1 (unsigned long ops)
* SHR reg, 1
* RCR reg, 1
* Eg: SHR dx, 1
* RCR ax, 1
* => dx:ax = dx:ax >> 1 (dx:ax are unsigned long)
* Found in Microsoft C code for long unsigned variable shift right.
****************************************************************************/
bool Idiom9::match(iICODE pIcode)
{
if(distance(pIcode,m_end)<2)
return false;
m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++;
if (m_icodes[0]->isLlFlag(I) && (m_icodes[0]->ic.ll.src.op() == 1))
if (m_icodes[1]->ic.ll.match(iRCR) &&
m_icodes[1]->isLlFlag(I) && (m_icodes[1]->ic.ll.src.op() == 1))
return true;
return false;
}
int Idiom9::action()
{
int idx;
COND_EXPR *rhs,*lhs,*expr;
byte regH,regL;
regL=m_icodes[1]->ic.ll.dst.regi;
regH=m_icodes[0]->ic.ll.dst.regi;
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN,regH,regL,m_icodes[0]);
lhs = COND_EXPR::idLongIdx (idx);
m_icodes[0]->setRegDU(regL, USE_DEF);
rhs = COND_EXPR::idKte (1, 2);
expr = COND_EXPR::boolOp (lhs, rhs, SHR);
m_icodes[0]->setAsgn(lhs, expr);
m_icodes[1]->invalidate();
return 2;
}

173
src/idioms/xor_idioms.cpp Normal file
View File

@ -0,0 +1,173 @@
#include "dcc.h"
#include "xor_idioms.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]->isLlFlag(I))
return false;
dst = &m_icodes[0]->ic.ll.dst;
src = &m_icodes[0]->ic.ll.src;
if ((dst->regi == src->regi) && (dst->regi > 0) && (dst->regi < INDEXBASE))
{
if ((dst->regi == rDX) && m_icodes[1]->ic.ll.match(rAX))
return true;
if ((dst->regi == rCX) && m_icodes[1]->ic.ll.match(rBX))
return true;
}
return false;
}
int Idiom21::action()
{
COND_EXPR *lhs,*rhs;
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0],HIGH_FIRST, m_icodes[0], eDEF, 1);
rhs = COND_EXPR::idKte (m_icodes[1]->ic.ll.src.op() , 4);
m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[0]->du.use = 0; /* 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;
LLOperand *dst, *src;
m_icode=picode;
dst = &picode->ic.ll.dst;
src = &picode->ic.ll.src;
if (dst->regi == 0) /* global variable */
{
if ((dst->segValue == src->segValue) && (dst->off == src->off))
return true;
}
else if (dst->regi < INDEXBASE) /* register */
{
if (dst->regi == src->regi)
return true;
}
else if ((dst->off) && (dst->seg == rSS) && (dst->regi == INDEXBASE + 6)) /* offset from BP */
{
if ((dst->off == src->off) && (dst->seg == src->seg) && (dst->regi == src->regi))
return true;
}
return false;
}
int Idiom7::action()
{
COND_EXPR *lhs,*rhs;
lhs = COND_EXPR::id (*m_icode, DST, m_func, m_icode, *m_icode, NONE);
rhs = COND_EXPR::idKte (0, 2);
m_icode->setAsgn(lhs, rhs);
m_icode->du.use = 0; /* clear register used in iXOR */
m_icode->ic.ll.flg |= 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]->isLlFlag(I) &&
(m_icodes[0]->ic.ll.src.regi > 0) &&
(m_icodes[0]->ic.ll.src.regi < INDEXBASE) &&
(m_icodes[0]->ic.ll.src.regi == m_icodes[0]->ic.ll.dst.regi))
if (m_icodes[1]->ic.ll.match(iJNE)) //.conditionalJump()
{
return true;
}
return false;
}
int Idiom10::action()
{
m_icodes[0]->ic.ll.opcode = iCMP;
m_icodes[0]->ic.ll.flg |= I;
m_icodes[0]->ic.ll.src.SetImmediateOp(0); // todo check if proc should be zeroed too
m_icodes[0]->du.def = 0;
m_icodes[0]->du1.numRegsDef = 0;
return 2;
}
/*****************************************************************************
* idiom10 - Jump if not equal to 0
* OR reg, reg
* JNE labX
* Eg: OR ax, ax
* JNE labX
* => HLI_JCOND (ax != 0) labX
* Note: we also check that these instructions are not followed by
* CMP reg, kte
* JE lab
* because this is most likely a long conditional equality test.
* Found in Borland Turbo C.
****************************************************************************/
static boolT idiom10old (iICODE pIcode, iICODE pEnd)
{
if (pIcode < pEnd)
{
/* Check OR reg, reg */
if (((pIcode->ic.ll.flg & I) != I) &&
(pIcode->ic.ll.src. regi > 0) &&
(pIcode->ic.ll.src.regi < INDEXBASE) &&
(pIcode->ic.ll.src.regi == pIcode->ic.ll.dst.regi))
if ((pIcode+3) < pEnd)
{
if (((pIcode+1)->ic.ll.opcode == iJNE) &&
((pIcode+2)->ic.ll.opcode != iCMP) &&
((pIcode+3)->ic.ll.opcode != iJE))
return true;
}
else /* at the end of the procedure */
if (((pIcode+1) < pEnd) && ((pIcode+1)->ic.ll.opcode == iJNE))
return true;
}
return false;
}