Explorar o código

fixed refactoring bugs

Artur K %!s(int64=12) %!d(string=hai) anos
pai
achega
777a260300

+ 75 - 0
include/idioms/arith_idioms.h

@@ -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 - 0
include/idioms/call_idioms.h

@@ -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 - 0
include/idioms/epilogue_idioms.h

@@ -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 - 0
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;
+    }
+};

+ 17 - 0
include/idioms/idiom1.h

@@ -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 - 0
include/idioms/mov_idioms.h

@@ -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 - 0
include/idioms/neg_idioms.h

@@ -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 - 0
include/idioms/shift_idioms.h

@@ -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 - 0
include/idioms/xor_idioms.h

@@ -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 - 0
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;
+}

+ 115 - 0
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; 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 - 0
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; 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 - 0
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<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 - 0
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;
+}
+

+ 102 - 0
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;
+}

+ 176 - 0
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; 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 - 0
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;
+}
+
+