123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- #include "arith_idioms.h"
- #include "dcc.h"
- #include "msvc_fixes.h"
- #include <QtCore/QDebug>
- 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]->ll()->match(iADC))
- return true;
- return false;
- }
- int Idiom5::action()
- {
- AstIdent *rhs,*lhs;
- Expr *expr;
- lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
- rhs = AstIdent::Long (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
- expr = new BinaryOperator(ADD,lhs, rhs);
- 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]->ll()->match(iSBB))
- return true;
- return false;
- }
- int Idiom6::action()
- {
- AstIdent *rhs,*lhs;
- Expr *expr;
- lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
- rhs = AstIdent::Long (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
- expr = new BinaryOperator(SUB,lhs, rhs);
- 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(picode==m_func->Icode.begin())
- return false;
- if(std::distance(picode,m_end)<3)
- return false;
- --picode; //
- for(int i=0; i<4; ++i)
- m_icodes[i] =picode++;
- m_idiom_type=-1;
- m_is_dec = m_icodes[1]->ll()->match(iDEC);
- uint8_t regi; /* register of the MOV */
- if(not m_icodes[0]->ll()->matchWithRegDst(iMOV) )
- return false;
- regi = m_icodes[0]->ll()->m_dst.regi;
- if( not ( m_icodes[2]->ll()->match(iCMP,regi) and
- m_icodes[3]->ll()->conditionalJump() ) )
- return false;
- // Simple matching finished, select apropriate matcher based on dst type
- /* Get variable */
- if (m_icodes[1]->ll()->m_dst.regi == 0) /* global variable */
- {
- /* not supported yet */
- m_idiom_type = 0;
- }
- else if ( m_icodes[1]->ll()->m_dst.isReg() ) /* register */
- {
- m_idiom_type = 1;
- // if ((m_icodes[1]->ll()->dst.regi == rSI) and (m_func->flg & SI_REGVAR))
- // m_idiom_type = 1;
- // else if ((m_icodes[1]->ll()->dst.regi == rDI) and (m_func->flg & DI_REGVAR))
- // m_idiom_type = 1;
- }
- else if (m_icodes[1]->ll()->m_dst.off) /* local variable */
- m_idiom_type = 2;
- else /* indexed */
- {
- m_idiom_type=3;
- /* not supported yet */
- ICODE &ic(*picode);
- const Function *my_proc(ic.getParent()->getParent());
- qWarning() << "Unsupported idiom18 type at"<< QString::number(ic.loc_ip,16)
- << "in"<< my_proc->name <<':'<< QString::number(my_proc->procEntry,16) << "- indexed";
- }
- switch(m_idiom_type)
- {
- case 0: // global
- printf("Unsupported idiom18 type at %x : global variable\n",picode->loc_ip);
- break;
- case 1: /* register variable */
- /* Check previous instruction for a MOV */
- if ( (m_icodes[0]->ll()->src().regi == m_icodes[1]->ll()->m_dst.regi))
- {
- return true;
- }
- break;
- case 2: /* local */
- if ((m_icodes[0]->ll()->src().off == m_icodes[1]->ll()->m_dst.off))
- {
- return true;
- }
- break;
- case 3: // indexed
- printf("Untested idiom18 type: indexed\n");
- if ((m_icodes[0]->ll()->src() == m_icodes[1]->ll()->m_dst))
- {
- return true;
- }
- break;
- }
- return false;
- }
- int Idiom18::action() // action length
- {
- Expr *rhs,*lhs;/* Pointers to left and right hand side exps */
- Expr *expr;
- lhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[1], *m_icodes[1], eUSE);
- lhs = UnaryOperator::Create(m_is_dec ? POST_DEC : POST_INC, lhs);
- rhs = AstIdent::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[1], *m_icodes[3], eUSE);
- expr = new BinaryOperator(condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB],lhs, rhs);
- m_icodes[3]->setJCond(expr);
- m_icodes[0]->invalidate();
- m_icodes[1]->invalidate();
- m_icodes[2]->invalidate();
- return 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;
- ICODE &ic(*picode);
- int type;
- for(int i=0; i<2; ++i)
- m_icodes[i] =picode++;
- m_is_dec = m_icodes[0]->ll()->match(iDEC);
- if ( not m_icodes[1]->ll()->conditionalJump() )
- return false;
- if (m_icodes[0]->ll()->m_dst.regi == 0) /* global variable */
- /* not supported yet */ ;
- else if ( m_icodes[0]->ll()->m_dst.isReg() ) /* register */
- {
- // if (((picode->ll()->dst.regi == rSI) and (pproc->flg & SI_REGVAR)) or
- // ((picode->ll()->dst.regi == rDI) and (pproc->flg & DI_REGVAR)))
- return true;
- }
- else if (m_icodes[0]->ll()->m_dst.off) /* stack variable */
- {
- return true;
- }
- else /* indexed */
- {
- fprintf(stderr,"idiom19 : Untested type [indexed]\n");
- return true;
- /* not supported yet */
- }
- return false;
- }
- int Idiom19::action()
- {
- Expr *lhs,*expr;
- lhs = AstIdent::id (*m_icodes[0]->ll(), DST, m_func, m_icodes[0], *m_icodes[1], eUSE);
- lhs = UnaryOperator::Create(m_is_dec ? PRE_DEC : PRE_INC, lhs);
- expr = new BinaryOperator(condOpJCond[m_icodes[1]->ll()->getOpcode() - iJB],lhs, new Constant(0, 2));
- 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 */
- uint8_t 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++;
- /* Check second instruction for a MOV */
- if( not m_icodes[1]->ll()->matchWithRegDst(iMOV) )
- return false;
- m_is_dec = m_icodes[0]->ll()->match(iDEC) ? PRE_DEC : PRE_INC;
- const LLOperand &ll_dest(m_icodes[0]->ll()->m_dst);
- /* Get variable */
- if (ll_dest.regi == 0) /* global variable */
- {
- /* not supported yet */ ;
- }
- else if ( ll_dest.isReg() ) /* register */
- {
- type = 1;
- // if ((ll_dest.regi == rSI) and (m_func->flg & SI_REGVAR))
- // type = 1;
- // else if ((ll_dest.regi == rDI) and (m_func->flg & DI_REGVAR))
- // type = 1;
- }
- else if (ll_dest.off) /* local variable */
- type = 2;
- else /* indexed */
- {
- printf("idiom20 : Untested type [indexed]\n");
- type = 3;
- /* not supported yet */ ;
- }
- regi = m_icodes[1]->ll()->m_dst.regi;
- const LLOperand &mov_src(m_icodes[1]->ll()->src());
- if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) and m_icodes[3]->ll()->conditionalJump())
- {
- switch(type)
- {
- case 1: /* register variable */
- if ((mov_src.regi == ll_dest.regi))
- {
- return true;
- }
- break;
- case 2: // local
- if ((mov_src.off == ll_dest.off))
- {
- return true;
- }
- break;
- case 3:
- fprintf(stderr,"Test 3 ");
- if ((mov_src == ll_dest))
- {
- return true;
- }
- break;
- }
- }
- return false;
- }
- int Idiom20::action()
- {
- Expr *lhs,*rhs,*expr;
- lhs = AstIdent::id (*m_icodes[1]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], eUSE);
- lhs = UnaryOperator::Create(m_is_dec, lhs);
- rhs = AstIdent::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[0], *m_icodes[3], eUSE);
- expr = new BinaryOperator(condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB],lhs, rhs);
- m_icodes[3]->setJCond(expr);
- for(int i=0; i<3; ++i)
- m_icodes[i]->invalidate();
- return 4;
- }
|