diff --git a/include/idioms/arith_idioms.h b/include/idioms/arith_idioms.h new file mode 100644 index 0000000..a48e09b --- /dev/null +++ b/include/idioms/arith_idioms.h @@ -0,0 +1,75 @@ +#pragma once +#include +#include "idiom.h" +#include "icode.h" +#include + +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(); +}; diff --git a/include/idioms/call_idioms.h b/include/idioms/call_idioms.h new file mode 100644 index 0000000..c624933 --- /dev/null +++ b/include/idioms/call_idioms.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include "idiom.h" +#include "icode.h" +#include +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 m_icodes; +public: + virtual ~Idiom17() {} + Idiom17(Function *f) : CallIdiom(f) + { + } + uint8_t minimum_match_length() {return 2;} + bool match(iICODE pIcode); + int action(); +}; diff --git a/include/idioms/epilogue_idioms.h b/include/idioms/epilogue_idioms.h new file mode 100644 index 0000000..daf5c0d --- /dev/null +++ b/include/idioms/epilogue_idioms.h @@ -0,0 +1,39 @@ +#pragma once +#include "idiom.h" +#include "icode.h" +#include +struct EpilogIdiom : public Idiom +{ +protected: + std::deque 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(); +}; diff --git a/include/idioms/idiom.h b/include/idioms/idiom.h new file mode 100644 index 0000000..9b09a98 --- /dev/null +++ b/include/idioms/idiom.h @@ -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; + } +}; diff --git a/include/idioms/idiom1.h b/include/idioms/idiom1.h new file mode 100644 index 0000000..5f6c543 --- /dev/null +++ b/include/idioms/idiom1.h @@ -0,0 +1,17 @@ +#pragma once +#include "idiom.h" +struct Idiom1 : public Idiom +{ +protected: + std::vector 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();} +}; diff --git a/include/idioms/mov_idioms.h b/include/idioms/mov_idioms.h new file mode 100644 index 0000000..bcdf390 --- /dev/null +++ b/include/idioms/mov_idioms.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include "idiom.h" +#include "icode.h" +#include + +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(); +}; diff --git a/include/idioms/neg_idioms.h b/include/idioms/neg_idioms.h new file mode 100644 index 0000000..613ef87 --- /dev/null +++ b/include/idioms/neg_idioms.h @@ -0,0 +1,33 @@ +#pragma once +#include +#include "idiom.h" +#include "icode.h" +#include + +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(); +}; diff --git a/include/idioms/shift_idioms.h b/include/idioms/shift_idioms.h new file mode 100644 index 0000000..65963bd --- /dev/null +++ b/include/idioms/shift_idioms.h @@ -0,0 +1,66 @@ +#pragma once +#include +#include "idiom.h" +#include "icode.h" +#include + +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 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(); +}; + diff --git a/include/idioms/xor_idioms.h b/include/idioms/xor_idioms.h new file mode 100644 index 0000000..3698286 --- /dev/null +++ b/include/idioms/xor_idioms.h @@ -0,0 +1,46 @@ +#pragma once +#include +#include "idiom.h" +#include "icode.h" +#include + +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(); +}; diff --git a/src/idioms/arith_idioms.cpp b/src/idioms/arith_idioms.cpp new file mode 100644 index 0000000..1dc61fc --- /dev/null +++ b/src/idioms/arith_idioms.cpp @@ -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; +} diff --git a/src/idioms/call_idioms.cpp b/src/idioms/call_idioms.cpp new file mode 100644 index 0000000..753f646 --- /dev/null +++ b/src/idioms/call_idioms.cpp @@ -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; idxinvalidate(); + } + } + // TODO : it's a calculated call + else + { + printf("Indirect call at idiom17\n"); + } + return m_icodes.size(); +} diff --git a/src/idioms/epilogue_idioms.cpp b/src/idioms/epilogue_idioms.cpp new file mode 100644 index 0000000..3ee9cdc --- /dev/null +++ b/src/idioms/epilogue_idioms.cpp @@ -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; idxinvalidate(); + 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; idxinvalidate(); + if(m_param_count) + { + m_func->cbParam = (int16)m_param_count; + m_func->flg |= CALL_PASCAL; + } + return 1; +} + diff --git a/src/idioms/idiom1.cpp b/src/idioms/idiom1.cpp new file mode 100644 index 0000000..d94a32e --- /dev/null +++ b/src/idioms/idiom1.cpp @@ -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 0) + { + for(int i=0; iic.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; iinvalidate(); + } + 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(); +} diff --git a/src/idioms/mov_idioms.cpp b/src/idioms/mov_idioms.cpp new file mode 100644 index 0000000..3194181 --- /dev/null +++ b/src/idioms/mov_idioms.cpp @@ -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; +} + diff --git a/src/idioms/neg_idioms.cpp b/src/idioms/neg_idioms.cpp new file mode 100644 index 0000000..ace68d1 --- /dev/null +++ b/src/idioms/neg_idioms.cpp @@ -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; +} diff --git a/src/idioms/shift_idioms.cpp b/src/idioms/shift_idioms.cpp new file mode 100644 index 0000000..9d5cc04 --- /dev/null +++ b/src/idioms/shift_idioms.cpp @@ -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; iinvalidate(); + } + 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; +} diff --git a/src/idioms/xor_idioms.cpp b/src/idioms/xor_idioms.cpp new file mode 100644 index 0000000..0878a1e --- /dev/null +++ b/src/idioms/xor_idioms.cpp @@ -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; +} + +