fixed refactoring bugs
This commit is contained in:
parent
11ae65efba
commit
777a260300
75
include/idioms/arith_idioms.h
Normal file
75
include/idioms/arith_idioms.h
Normal 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();
|
||||
};
|
||||
42
include/idioms/call_idioms.h
Normal file
42
include/idioms/call_idioms.h
Normal 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();
|
||||
};
|
||||
39
include/idioms/epilogue_idioms.h
Normal file
39
include/idioms/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();
|
||||
};
|
||||
22
include/idioms/idiom.h
Normal file
22
include/idioms/idiom.h
Normal 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
17
include/idioms/idiom1.h
Normal 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();}
|
||||
};
|
||||
36
include/idioms/mov_idioms.h
Normal file
36
include/idioms/mov_idioms.h
Normal 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();
|
||||
};
|
||||
33
include/idioms/neg_idioms.h
Normal file
33
include/idioms/neg_idioms.h
Normal 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();
|
||||
};
|
||||
66
include/idioms/shift_idioms.h
Normal file
66
include/idioms/shift_idioms.h
Normal 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();
|
||||
};
|
||||
|
||||
46
include/idioms/xor_idioms.h
Normal file
46
include/idioms/xor_idioms.h
Normal 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
327
src/idioms/arith_idioms.cpp
Normal 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
115
src/idioms/call_idioms.cpp
Normal 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();
|
||||
}
|
||||
139
src/idioms/epilogue_idioms.cpp
Normal file
139
src/idioms/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 1;
|
||||
}
|
||||
|
||||
137
src/idioms/idiom1.cpp
Normal file
137
src/idioms/idiom1.cpp
Normal 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
110
src/idioms/mov_idioms.cpp
Normal 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
102
src/idioms/neg_idioms.cpp
Normal 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
176
src/idioms/shift_idioms.cpp
Normal 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
173
src/idioms/xor_idioms.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user