diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e553ea..4f7832e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,8 @@ src/graph.cpp src/hlicode.cpp src/icode.cpp src/idioms.cpp +src/idiom1.cpp +src/epilogue_idioms.cpp src/locident.cpp src/parser.cpp src/perfhlib.cpp @@ -57,6 +59,9 @@ set(dcc_HEADERS include/graph.h include/hlicode.h include/icode.h + include/idiom.h + include/idiom1.h + include/epilogue_idioms.h include/locident.h include/perfhlib.h include/scanner.h diff --git a/include/icode.h b/include/icode.h index abc0175..2bc9169 100644 --- a/include/icode.h +++ b/include/icode.h @@ -63,32 +63,35 @@ enum eDuFlags }; /* Machine registers */ -#define rAX 1 /* These are numbered relative to real 8086 */ -#define rCX 2 -#define rDX 3 -#define rBX 4 -#define rSP 5 -#define rBP 6 -#define rSI 7 -#define rDI 8 +enum eReg +{ +rAX = 1, /* These are numbered relative to real 8086 */ +rCX = 2, +rDX = 3, +rBX = 4, +rSP = 5, +rBP = 6, +rSI = 7, +rDI = 8, -#define rES 9 -#define rCS 10 -#define rSS 11 -#define rDS 12 +rES = 9, +rCS = 10, +rSS = 11, +rDS = 12, -#define rAL 13 -#define rCL 14 -#define rDL 15 -#define rBL 16 -#define rAH 17 -#define rCH 18 -#define rDH 19 -#define rBH 20 +rAL = 13, +rCL = 14, +rDL = 15, +rBL = 16, +rAH = 17, +rCH = 18, +rDH = 19, +rBH = 20, -#define rTMP 21 /* temp register for DIV/IDIV/MOD */ +rTMP= 21 /* temp register for DIV/IDIV/MOD */ #define INDEXBASE 22 /* Indexed modes go from INDEXBASE to - * INDEXBASE+7 */ + * INDEXBASE+7 */ +}; /* Byte and Word registers */ static const char *const byteReg[9] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", "tmp" }; @@ -314,6 +317,26 @@ struct LLInst : public llvm::MCInst return (opcode >= iJB) && (opcode < iJCXZ); } bool anyFlagSet(uint32_t x) const { return (flg & x)!=0;} + bool match(llIcode op) + { + return (opcode==op); + } + bool match(llIcode op,eReg dest) + { + return (opcode==op)&&dst.regi==dest; + } + bool match(llIcode op,eReg dest,eReg src_reg) + { + return (opcode==op)&&(dst.regi==dest)&&(src.regi==src_reg); + } + bool match(eReg dest,eReg src_reg) + { + return (dst.regi==dest)&&(src.regi==src_reg); + } + bool match(eReg dest) + { + return (dst.regi==dest); + } }; /* Icode definition: LOW_LEVEL and HIGH_LEVEL */ @@ -338,13 +361,13 @@ struct ICODE IC ic;/* intermediate code */ int loc_ip; // used by CICodeRec to number ICODEs - void ClrLlFlag(dword flag) {ic.ll.flg &= ~flag;} - void SetLlFlag(dword flag) {ic.ll.flg |= flag;} - dword GetLlFlag() {return ic.ll.flg;} - bool isLlFlag(dword flg) {return (ic.ll.flg&flg)!=0;} + void ClrLlFlag(dword flag) {ic.ll.flg &= ~flag;} + void SetLlFlag(dword flag) {ic.ll.flg |= flag;} + dword GetLlFlag() {return ic.ll.flg;} + bool isLlFlag(dword flg) {return (ic.ll.flg&flg)!=0;} llIcode GetLlOpcode() const { return ic.ll.opcode; } - dword GetLlLabel() const { return ic.ll.label;} - void SetImmediateOp(dword dw) {ic.ll.src.SetImmediateOp(dw);} + dword GetLlLabel() const { return ic.ll.label;} + void SetImmediateOp(dword dw) {ic.ll.src.SetImmediateOp(dw);} void writeIntComment(std::ostringstream &s); void setRegDU(byte regi, operDu du_in); @@ -372,6 +395,7 @@ public: ICODE * addIcode(ICODE *pIcode); void SetInBB(int start, int end, BB* pnewBB); bool labelSrch(dword target, dword &pIndex); + iterator labelSrch(dword target); ICODE * GetIcode(int ip); }; typedef CIcodeRec::iterator iICODE; diff --git a/src/icode.cpp b/src/icode.cpp index 0746c66..78ea6e8 100644 --- a/src/icode.cpp +++ b/src/icode.cpp @@ -50,7 +50,19 @@ bool CIcodeRec::labelSrch(dword target, dword &pIndex) } return false; } +CIcodeRec::iterator CIcodeRec::labelSrch(dword target) +{ + Int i; + for (i = 0; i < size(); i++) + { + if (at(i).ic.ll.label == target) + { + return begin()+i; + } + } + return end(); +} ICODE * CIcodeRec::GetIcode(int ip) { return &at(ip); diff --git a/src/idioms.cpp b/src/idioms.cpp index 06401b7..d8fb42e 100644 --- a/src/idioms.cpp +++ b/src/idioms.cpp @@ -3,12 +3,12 @@ * (C) Cristina Cifuentes ****************************************************************************/ +#include +#include +#include "idiom.h" +#include "idiom1.h" +#include "epilogue_idioms.h" #include "dcc.h" -#include -#ifdef __DOSWIN__ -#include -#endif - /***************************************************************************** * JmpInst - Returns TRUE if opcode is a conditional or unconditional jump @@ -16,294 +16,17 @@ bool JmpInst(llIcode opcode) { switch (opcode) { - case iJMP: case iJMPF: case iJCXZ: - case iLOOP: case iLOOPE:case iLOOPNE: - case iJB: case iJBE: case iJAE: case iJA: - case iJL: case iJLE: case iJGE: case iJG: - case iJE: case iJNE: case iJS: case iJNS: - case iJO: case iJNO: case iJP: case iJNP: - return true; + case iJMP: case iJMPF: case iJCXZ: + case iLOOP: case iLOOPE:case iLOOPNE: + case iJB: case iJBE: case iJAE: case iJA: + case iJL: case iJLE: case iJGE: case iJG: + case iJE: case iJNE: case iJS: case iJNS: + case iJO: case iJNO: case iJP: case iJNP: + return true; } return false; } - -/***************************************************************************** -/* checkStkVars - Checks for PUSH SI - * [PUSH DI] - * or PUSH DI - * [PUSH SI] - * In which case, the stack variable flags are set - ****************************************************************************/ -static Int checkStkVars (iICODE pIcode, iICODE pEnd, Function * pProc) -{ - /* Look for PUSH SI */ - if ((pIcode < pEnd) && (pIcode->ic.ll.opcode == iPUSH) && - (pIcode->ic.ll.dst.regi == rSI)) - { - pProc->flg |= SI_REGVAR; - - /* Look for PUSH DI */ - if (++pIcode < pEnd && (pIcode->ic.ll.opcode == iPUSH) && - (pIcode->ic.ll.dst.regi == rDI)) - { - pProc->flg |= DI_REGVAR; - return 2; - } - else - return 1; - } - else if ((pIcode < pEnd) && (pIcode->ic.ll.opcode == iPUSH) && - (pIcode->ic.ll.dst.regi == rDI)) - { - pProc->flg |= DI_REGVAR; - - /* Look for PUSH SI */ - if ((++pIcode < pEnd) && (pIcode->ic.ll.opcode == iPUSH) && - (pIcode->ic.ll.dst.regi == rSI)) - { - pProc->flg |= SI_REGVAR; - return 2; - } - else - return 1; - } - return 0; -} -typedef std::list::iterator cITER; -static Int checkStkVars (cITER pIcode, cITER pEnd, Function * pProc) -{ - /* Look for PUSH SI */ - if ((pIcode != pEnd) && (pIcode->ic.ll.opcode == iPUSH) && - (pIcode->ic.ll.dst.regi == rSI)) - { - pProc->flg |= SI_REGVAR; - - /* Look for PUSH DI */ - ++pIcode; - if (pIcode != pEnd && (pIcode->ic.ll.opcode == iPUSH) && (pIcode->ic.ll.dst.regi == rDI)) - { - pProc->flg |= DI_REGVAR; - return 2; - } - else - return 1; - } - else if ((pIcode != pEnd) && (pIcode->ic.ll.opcode == iPUSH) && - (pIcode->ic.ll.dst.regi == rDI)) - { - pProc->flg |= DI_REGVAR; - - /* Look for PUSH SI */ - ++pIcode; - if ((pIcode != pEnd) && (pIcode->ic.ll.opcode == iPUSH) && (pIcode->ic.ll.dst.regi == rSI)) - { - pProc->flg |= SI_REGVAR; - return 2; - } - else - return 1; - } - return 0; -} - -/***************************************************************************** - * 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] - ****************************************************************************/ -static Int idiom1(iICODE pIcode, iICODE pEnd, Function * pProc) -{ - std::vector entries; - Int n; - - /* PUSH BP as first instruction of procedure */ - if ( !(pIcode->ic.ll.flg & I) && pIcode->ic.ll.src.regi == rBP) - { - /* MOV BP, SP as next instruction */ - pIcode++; - if (pIcode < pEnd && ! (pIcode->ic.ll.flg & (I | TARGET | CASE)) - && pIcode->ic.ll.opcode == iMOV && pIcode->ic.ll.dst.regi == rBP - && pIcode->ic.ll.src.regi == rSP) - { - pProc->args.m_minOff = 2; - pProc->flg |= PROC_IS_HLL; - - /* Look for SUB SP, immed */ - if ((++pIcode < pEnd) && - (pIcode->ic.ll.flg & (I | TARGET | CASE)) == I && - pIcode->ic.ll.opcode == iSUB && pIcode->ic.ll.dst.regi == rSP) - { - return (3 + checkStkVars (++pIcode, pEnd, pProc)); - } - else - return (2 + checkStkVars (pIcode, pEnd, pProc)); - } - - /* PUSH SI - * [PUSH DI] - * MOV BP, SP */ - else - { - n = checkStkVars (pIcode, pEnd, pProc); - if (n > 0) - { - /* Look for MOV BP, SP */ - pIcode += n; - if (pIcode < pEnd && - ! (pIcode->ic.ll.flg & (I | TARGET | CASE)) && - pIcode->ic.ll.opcode == iMOV && - pIcode->ic.ll.dst.regi == rBP && - pIcode->ic.ll.src.regi == rSP) - { - pProc->args.m_minOff = 2 + (n * 2); - return (2 + n); - } - else return 0; // Cristina: check this please! - } - else return 0; // Cristina: check this please! - } - } - else - return (checkStkVars (pIcode, pEnd, pProc)); -} -static Int idiom1x(cITER pIcode, cITER pEnd, Function * pProc) -{ - Int n; - - /* PUSH BP as first instruction of procedure */ - if ( !(pIcode->ic.ll.flg & I) && pIcode->ic.ll.src.regi == rBP) - { - /* MOV BP, SP as next instruction */ - pIcode++; - if (pIcode != pEnd && ! (pIcode->ic.ll.flg & (I | TARGET | CASE)) - && pIcode->ic.ll.opcode == iMOV && pIcode->ic.ll.dst.regi == rBP - && pIcode->ic.ll.src.regi == rSP) - { - pProc->args.m_minOff = 2; - pProc->flg |= PROC_IS_HLL; - - /* Look for SUB SP, immed */ - ++pIcode; - if ((pIcode != pEnd) && - (pIcode->ic.ll.flg & (I | TARGET | CASE)) == I && - pIcode->ic.ll.opcode == iSUB && pIcode->ic.ll.dst.regi == rSP) - { - return (3 + checkStkVars (++pIcode, pEnd, pProc)); - } - else - return (2 + checkStkVars (pIcode, pEnd, pProc)); - } - - /* PUSH SI - * [PUSH DI] - * MOV BP, SP */ - else - { - n = checkStkVars (pIcode, pEnd, pProc); - if (n > 0) - { - /* Look for MOV BP, SP */ - std::advance(pIcode,n); - if (pIcode != pEnd && - ! (pIcode->ic.ll.flg & (I | TARGET | CASE)) && - pIcode->ic.ll.opcode == iMOV && - pIcode->ic.ll.dst.regi == rBP && - pIcode->ic.ll.src.regi == rSP) - { - pProc->args.m_minOff = 2 + (n * 2); - return (2 + n); - } - else return 0; // Cristina: check this please! - } - else return 0; // Cristina: check this please! - } - } - else - return (checkStkVars (pIcode, pEnd, pProc)); -} - -/***************************************************************************** - * popStkVars - checks for - * [POP DI] - * [POP SI] - * or [POP SI] - * [POP DI] - ****************************************************************************/ -static void popStkVars (iICODE pIcode, iICODE pEnd, Function * pProc) -{ - /* Match [POP DI] */ - if (pIcode->ic.ll.opcode == iPOP) - if ((pProc->flg & DI_REGVAR) && (pIcode->ic.ll.dst.regi == rDI)) - pIcode->invalidate(); - else if ((pProc->flg & SI_REGVAR) && (pIcode->ic.ll.dst.regi == rSI)) - pIcode->invalidate(); - - /* Match [POP SI] */ - if ((pIcode+1)->ic.ll.opcode == iPOP) - if ((pProc->flg & SI_REGVAR) && ((pIcode+1)->ic.ll.dst.regi == rSI)) - (pIcode+1)->invalidate(); - else if ((pProc->flg & DI_REGVAR) && ((pIcode+1)->ic.ll.dst.regi == rDI)) - (pIcode+1)->invalidate(); -} - - -/***************************************************************************** - * idiom2 - HLL procedure epilogue; Returns number of instructions matched. - * [POP DI] - * [POP SI] - * MOV SP, BP - * POP BP - * RET(F) - *****************************************************************************/ -static Int idiom2(iICODE pIcode, iICODE pEnd, Function * pProc) -{ - iICODE nicode; - - /* Match MOV SP, BP */ - if (pIcode->loc_ip != 0 && ((pIcode->ic.ll.flg & I) != I) && - pIcode->ic.ll.dst.regi == rSP && pIcode->ic.ll.src.regi == rBP) - { - /* Get next icode, skip over holes in the icode array */ - nicode = pIcode + 1; - while (nicode->ic.ll.flg & NO_CODE) - nicode++; - - /* Match POP BP */ - if (nicode < pEnd && - ! (nicode->ic.ll.flg & (I | TARGET | CASE)) && - nicode->ic.ll.opcode == iPOP && - nicode->ic.ll.dst.regi == rBP) - { - nicode++; - - /* Match RET(F) */ - if (nicode < pEnd && - ! (nicode->ic.ll.flg & (I | TARGET | CASE)) && - (nicode->ic.ll.opcode == iRET || - nicode->ic.ll.opcode == iRETF)) - { - popStkVars (pIcode-2, pEnd, pProc); - return 2; - } - } - } - return 0; -} - - - /***************************************************************************** * idiom3 - C calling convention. * CALL(F) proc_X @@ -317,18 +40,52 @@ static Int idiom2(iICODE pIcode, iICODE pEnd, Function * pProc) * Used by compilers to restore the stack when invoking a procedure using * the C calling convention. ****************************************************************************/ -static Int idiom3(iICODE pIcode, iICODE pEnd) +struct Idiom3 : public Idiom { - /* Match ADD SP, immed */ - ++pIcode; - if ((pIcode < pEnd) && (pIcode->ic.ll.flg & I) && - (pIcode->ic.ll.opcode == iADD) && (pIcode->ic.ll.dst.regi == rSP)) - return (pIcode->ic.ll.src.op()); - else if ((pIcode->ic.ll.opcode == iMOV) && (pIcode->ic.ll.dst.regi == rSP) - && (pIcode->ic.ll.src.regi == rBP)) - (pIcode-1)->ic.ll.flg |= REST_STK; - return 0; -} +protected: + iICODE m_icodes[2]; + int m_param_count; +public: + Idiom3(Function *f) : Idiom(f) + { + } + uint8_t minimum_match_length() {return 2;} + bool 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 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; + } +}; /***************************************************************************** @@ -343,72 +100,68 @@ static Int idiom3(iICODE pIcode, iICODE pEnd) * 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. ****************************************************************************/ -static Int idiom17 (iICODE pIcode, iICODE pEnd) +struct Idiom17 : public Idiom { - Int i = 0; /* Count on # pops */ - byte regi; - - /* Match POP reg */ - ++pIcode; - if ((pIcode < pEnd) && (pIcode->ic.ll.opcode == iPOP)) +protected: + std::vector m_icodes; + int m_param_count; +public: + Idiom17(Function *f) : Idiom(f) { - regi = pIcode->ic.ll.dst.regi; - if ((regi >= rAX) && (regi <= rBX)) - i++; - ++pIcode; - while (pIcode->ic.ll.opcode == iPOP) + } + uint8_t minimum_match_length() {return 2;} + bool 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)) { - if (pIcode->ic.ll.dst.regi == regi) - { + int i=0; + regi = m_icodes[1]->ic.ll.dst.regi; + if ((regi >= rAX) && (regi <= rBX)) i++; - ++pIcode; + + m_icodes.push_back(++picode); + while (m_icodes.back() != m_end && m_icodes.back()->ic.ll.match(iPOP)) + { + if (m_icodes.back()->ic.ll.dst.regi != regi) + break; + i++; + m_icodes.push_back(++picode); } - else - break; + m_param_count = i*2; } - return (i * 2); + return m_param_count!=0; } - return (0); -} - - -/***************************************************************************** - * 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] - ****************************************************************************/ -static void idiom4 (iICODE pIcode, iICODE pEnd, Function * pProc) -{ - /* Check for [POP DI] - * [POP SI] */ - popStkVars (pIcode-3, pEnd, pProc); - - /* Check for POP BP */ - if (((pIcode-1)->ic.ll.opcode == iPOP) && - (((pIcode-1)->ic.ll.flg & I) != I) && - ((pIcode-1)->ic.ll.dst.regi == rBP)) - (pIcode-1)->invalidate(); - else - popStkVars (pIcode-2, pEnd, pProc); - - /* Check for RET(F) immed */ - if (pIcode->ic.ll.flg & I) + int action() { - pProc->cbParam = (int16)pIcode->ic.ll.src.op(); - pProc->flg |= CALL_PASCAL; + 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(); } -} - +}; /***************************************************************************** * idiom5 - Long addition. @@ -422,9 +175,11 @@ static void idiom4 (iICODE pIcode, iICODE pEnd, Function * pProc) ****************************************************************************/ static boolT idiom5 (iICODE pIcode, iICODE pEnd) { - if (pIcode < pEnd) - if ((pIcode+1)->ic.ll.opcode == iADC) - return true; + iICODE next1=pIcode+1; + if (pIcode >= pEnd) + return false; + if (next1->ic.ll.match(iADC)) + return true; return false; } @@ -442,7 +197,7 @@ static boolT idiom5 (iICODE pIcode, iICODE pEnd) static boolT idiom6 (iICODE pIcode, iICODE pEnd) { if (pIcode < pEnd) - if ((pIcode+1)->ic.ll.opcode == iSBB) + if ((pIcode+1)->ic.ll.match(iSBB)) return true; return false; } @@ -475,7 +230,7 @@ static boolT idiom7 (iICODE pIcode) /* offset from BP */ { if ((dst->off == src->off) && (dst->seg == src->seg) && - (dst->regi == src->regi)) + (dst->regi == src->regi)) return true; } return false; @@ -498,17 +253,18 @@ static boolT idiom7 (iICODE pIcode) static boolT idiom21 (iICODE picode, iICODE pend) { LLOperand *dst, *src; - + iICODE next1=picode+1; + if(next1>=pend) + return false; dst = &picode->ic.ll.dst; src = &picode->ic.ll.src; - if (((picode+1) < pend) && ((picode+1)->ic.ll.flg & I)) + if (next1->ic.ll.flg & I) { - if ((dst->regi == src->regi) && (dst->regi > 0) && - (dst->regi < INDEXBASE)) + if ((dst->regi == src->regi) && (dst->regi > 0) && (dst->regi < INDEXBASE)) { - if ((dst->regi == rDX) && ((picode+1)->ic.ll.dst.regi == rAX)) + if ((dst->regi == rDX) && (next1->ic.ll.dst.regi == rAX)) return true; - if ((dst->regi == rCX) && ((picode+1)->ic.ll.dst.regi == rBX)) + if ((dst->regi == rCX) && (next1->ic.ll.dst.regi == rBX)) return true; } } @@ -532,8 +288,8 @@ static boolT idiom8 (iICODE pIcode, iICODE pEnd) return false; if (pIcode->ic.ll.anyFlagSet(I) && (pIcode->ic.ll.src.op() == 1)) if ((next->ic.ll.opcode == iRCR) && - next->ic.ll.anyFlagSet(I) && - (next->ic.ll.src.op() == 1)) + next->ic.ll.anyFlagSet(I) && + (next->ic.ll.src.op() == 1)) return true; return false; } @@ -564,9 +320,9 @@ static Int idiom15 (iICODE picode, iICODE pend) for(auto iter=picode+1;iter < pend;++iter) { if ((iter->ic.ll.opcode == iSHL) && - (iter->ic.ll.flg & I) && - (iter->ic.ll.src.op() == 1) && - (iter->ic.ll.dst.regi == regi)) + (iter->ic.ll.flg & I) && + (iter->ic.ll.src.op() == 1) && + (iter->ic.ll.dst.regi == regi)) n++; else break; @@ -596,8 +352,8 @@ static boolT idiom12 (iICODE pIcode, iICODE pEnd) { if (pIcode->ic.ll.anyFlagSet(I) && (pIcode->ic.ll.src.op() == 1)) if ((next->ic.ll.opcode == iRCL) && - (next->ic.ll.anyFlagSet(I)) && - (next->ic.ll.src.op() == 1)) + (next->ic.ll.anyFlagSet(I)) && + (next->ic.ll.src.op() == 1)) return true; } return false; @@ -620,8 +376,8 @@ static boolT idiom9 (iICODE pIcode, iICODE pEnd) { if (((pIcode->ic.ll.flg & I) == I) && (pIcode->ic.ll.src.op() == 1)) if ((next->ic.ll.opcode == iRCR) && - ((next->ic.ll.flg & I) == I) && - (next->ic.ll.src.op() == 1)) + ((next->ic.ll.flg & I) == I) && + (next->ic.ll.src.op() == 1)) return true; } return false; @@ -647,14 +403,14 @@ static boolT idiom10old (iICODE pIcode, iICODE 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)) + (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)) + ((pIcode+2)->ic.ll.opcode != iCMP) && + ((pIcode+3)->ic.ll.opcode != iJE)) return true; } else /* at the end of the procedure */ @@ -686,9 +442,9 @@ static void idiom10 (iICODE pIcode, iICODE pEnd) return; /* 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)) + (pIcode->ic.ll.src.regi > 0) && + (pIcode->ic.ll.src.regi < INDEXBASE) && + (pIcode->ic.ll.src.regi == pIcode->ic.ll.dst.regi)) if (next->ic.ll.opcode == iJNE) { pIcode->ic.ll.opcode = iCMP; @@ -723,8 +479,8 @@ static byte idiom13 (iICODE pIcode, iICODE pEnd) { /* Check for MOV regH, 0 */ if ((next->ic.ll.opcode == iMOV) && - (next->ic.ll.flg & I) && - (next->ic.ll.src.op() == 0)) + (next->ic.ll.flg & I) && + (next->ic.ll.src.op() == 0)) { if (next->ic.ll.dst.regi == (regi + 4)) return (regi - rAL + rAX); @@ -754,24 +510,23 @@ static byte idiom13 (iICODE pIcode, iICODE pEnd) ****************************************************************************/ static boolT idiom14 (iICODE picode, iICODE pend, byte *regL, byte *regH) { - if (picode < pend) + if (picode >= pend) + return false; + iICODE next1=picode+1; + /* Check for regL */ + *regL = picode->ic.ll.dst.regi; + if (((picode->ic.ll.flg & I) != I) && ((*regL == rAX) || (*regL ==rBX))) { - /* Check for regL */ - *regL = picode->ic.ll.dst.regi; - if (((picode->ic.ll.flg & I) != I) && ((*regL == rAX) || (*regL ==rBX))) + /* Check for XOR regH, regH */ + if ((next1->ic.ll.opcode == iXOR) && ((next1->ic.ll.flg & I) != I)) { - /* Check for XOR regH, regH */ - if (((picode+1)->ic.ll.opcode == iXOR) && - (((picode+1)->ic.ll.flg & I) != I)) + *regH = next1->ic.ll.dst.regi; + if (*regH == next1->ic.ll.src.regi) { - *regH = (picode+1)->ic.ll.dst.regi; - if (*regH == (picode+1)->ic.ll.src.regi) - { - if ((*regL == rAX) && (*regH == rDX)) - return true; - if ((*regL == rBX) && (*regH == rCX)) - return true; - } + if ((*regL == rAX) && (*regH == rDX)) + return true; + if ((*regL == rBX) && (*regH == rCX)) + return true; } } } @@ -790,37 +545,38 @@ static boolT idiom14 (iICODE picode, iICODE pend, byte *regL, byte *regH) * Found in Borland Turbo C. ****************************************************************************/ static boolT idiom11 (iICODE pIcode, iICODE pEnd) -{ condId type; /* type of argument */ - - if ((pIcode + 2) < pEnd) +{ + condId type; /* type of argument */ + const char *matchstring="(oNEG rH) (oNEG rL) (SBB \rH i0)"; + iICODE next2 = pIcode+2; + if (next2 < pEnd) + { + type = pIcode->idType(DST); + if ((type != CONSTANT) && (type != OTHER)) { - type = pIcode->idType(DST); - if ((type != CONSTANT) && (type != OTHER)) - { /* Check NEG reg/mem * SBB reg/mem, 0*/ - if (((pIcode+1)->ic.ll.opcode == iNEG) && - ((pIcode+2)->ic.ll.opcode == iSBB)) - switch (type) { - case GLOB_VAR: if (((pIcode+2)->ic.ll.dst.segValue == - pIcode->ic.ll.dst.segValue) && - ((pIcode+2)->ic.ll.dst.off == - pIcode->ic.ll.dst.off)) - return true; - break; - case REGISTER: if ((pIcode+2)->ic.ll.dst.regi == - pIcode->ic.ll.dst.regi) - return true; - break; - case PARAM: - case LOCAL_VAR: if ((pIcode+2)->ic.ll.dst.off == - pIcode->ic.ll.dst.off) - return true; - break; - } - } + if (((pIcode+1)->ic.ll.match(iNEG)) && next2->ic.ll.match(iSBB)) + switch (type) + { + case GLOB_VAR: + if ((next2->ic.ll.dst.segValue == pIcode->ic.ll.dst.segValue) && + (next2->ic.ll.dst.off == pIcode->ic.ll.dst.off)) + return true; + break; + case REGISTER: + if (next2->ic.ll.dst.regi == pIcode->ic.ll.dst.regi) + return true; + break; + case PARAM: + case LOCAL_VAR: + if (next2->ic.ll.dst.off == pIcode->ic.ll.dst.off) + return true; + break; + } } - return false; + } + return false; } @@ -837,21 +593,20 @@ static boolT idiom11 (iICODE pIcode, iICODE pEnd) * Found in Borland Turbo C when negating bitwise. ****************************************************************************/ static boolT idiom16 (iICODE picode, iICODE pend) -{ byte regi; - - if ((picode+2) < pend) +{ + const char *matchstring="(oNEG rR) (oSBB rR rR) (oINC rR)"; + byte regi; + iICODE next1(picode+1),next2(picode+2); + if (next2 >= pend) + return false; + regi = picode->ic.ll.dst.regi; + if ((regi >= rAX) && (regi < INDEXBASE)) { - regi = picode->ic.ll.dst.regi; - if ((regi >= rAX) && (regi < INDEXBASE)) - { - if (((picode+1)->ic.ll.opcode == iSBB) && - ((picode+2)->ic.ll.opcode == iINC)) - if (((picode+1)->ic.ll.dst.regi == - ((picode+1)->ic.ll.src.regi)) && - ((picode+1)->ic.ll.dst.regi == regi) && - ((picode+2)->ic.ll.dst.regi == regi)) - return true; - } + if (next1->ic.ll.match(iSBB) && (next2->ic.ll.opcode == iINC)) + if ((next1->ic.ll.dst.regi == (next1->ic.ll.src.regi)) && + (next1->ic.ll.dst.regi == regi) && + (next2->ic.ll.dst.regi == regi)) + return true; } return false; } @@ -861,7 +616,7 @@ static boolT idiom16 (iICODE picode, iICODE pend) * 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 + * 1 INC var or DEC var <------------------------- input point * 2 CMP var, Y * 3 JX label * => HLI_JCOND (var++ X Y) @@ -872,65 +627,77 @@ static boolT idiom16 (iICODE picode, iICODE pend) * => HLI_JCOND (si++ < 8) * Found in Borland Turbo C. Intrinsic to C languages. ****************************************************************************/ -static boolT idiom18 (iICODE picode, iICODE pend, Function * pproc) +struct Idiom18 : public Idiom { - assert(picode+2<=pend); - std::vector used; - for(int i=0; i<4; i++) +protected: + iICODE m_icodes[4]; + bool m_is_dec; +public: + Idiom18(Function *f) : Idiom(f) { - used.push_back(picode-1+i); } - int type = -1; /* type of variable: 1 = reg-var, 2 = local */ - byte regi; /* register of the MOV */ + uint8_t minimum_match_length() {return 4;} + bool match(iICODE picode) + { + if(std::distance(picode,m_end)<2) + return false; + --picode; // - /* Get variable */ - if (used[1]->ic.ll.dst.regi == 0) /* global variable */ - { - /* not supported yet */ - type = 0; - } - else if (used[1]->ic.ll.dst.regi < INDEXBASE) /* register */ - { - if ((used[1]->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR)) - type = 1; - else if ((used[1]->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR)) - type = 1; - } - else if (used[1]->ic.ll.dst.off) /* local variable */ - type = 2; - else /* indexed */ - { - type=3; - /* not supported yet */ - printf("Unsupported idiom18 type: indexed"); - } + for(int i=0; i<4; ++i) + m_icodes[i] =picode++; - switch(type) - { + 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 ((used[0]->ic.ll.opcode == iMOV) && (used[0]->ic.ll.src.regi == used[1]->ic.ll.dst.regi)) + if (m_icodes[0]->ic.ll.match(iMOV) && (m_icodes[0]->ic.ll.src.regi == m_icodes[1]->ic.ll.dst.regi)) { - regi = used[0]->ic.ll.dst.regi; + regi = m_icodes[0]->ic.ll.dst.regi; if ((regi > 0) && (regi < INDEXBASE)) { - if ( (used[2]->ic.ll.opcode == iCMP) && (used[2]->ic.ll.dst.regi == regi) && - used[3]->ic.ll.conditionalJump() ) + 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 ((used[0]->ic.ll.opcode == iMOV) && (used[0]->ic.ll.src.off == used[1]->ic.ll.dst.off)) + 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 = used[0]->ic.ll.dst.regi; + regi = m_icodes[0]->ic.ll.dst.regi; if ((regi > 0) && (regi < INDEXBASE)) { - if ( (used[2]->ic.ll.opcode == iCMP) && (used[2]->ic.ll.dst.regi == regi) && - used[3]->ic.ll.conditionalJump() ) + if ( m_icodes[2]->ic.ll.match(iCMP) && (m_icodes[2]->ic.ll.dst.regi == regi) && + m_icodes[3]->ic.ll.conditionalJump() ) return true; } } @@ -938,44 +705,84 @@ static boolT idiom18 (iICODE picode, iICODE pend, Function * pproc) case 3: // indexed printf("Unsupported idiom18 type: indexed"); break; + } + return false; } - return false; -} + int 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; + } +}; /***************************************************************************** - * idiom 19: pre-increment or pre-decrement in conditional jump, comparing - * against 0. - * INC var or DEC var (including register vars) - * JX lab JX lab + * 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 + * JG lab2 * => HLI_JCOND (++[bp+4] > 0) * Found in Borland Turbo C. Intrinsic to C language. ****************************************************************************/ -static boolT idiom19 (iICODE picode, iICODE pend, Function * pproc) +struct Idiom19 : public Idiom { - if (picode->ic.ll.dst.regi == 0) /* global variable */ - /* not supported yet */ ; - else if (picode->ic.ll.dst.regi < INDEXBASE) /* register */ +protected: + iICODE m_icodes[2]; + bool m_is_dec; +public: + Idiom19(Function *f) : Idiom(f) { - if (((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR)) || - ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR))) - if ((picode < pend) && ((picode+1)->ic.ll.opcode >= iJB) && - ((picode+1)->ic.ll.opcode < iJCXZ)) + } + uint8_t minimum_match_length() {return 2;} + bool match(iICODE picode) + { + if(std::distance(picode,m_end)<1) + 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; } - else if (picode->ic.ll.dst.off) /* stack variable */ + int action() { - if ((picode < pend) && ((picode+1)->ic.ll.opcode >= iJB) && - ((picode+1)->ic.ll.opcode < iJCXZ)) - return true; + 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; } - else /* indexed */ - /* not supported yet */ ; - return false; -} +}; /***************************************************************************** @@ -993,70 +800,99 @@ static boolT idiom19 (iICODE picode, iICODE pend, Function * pproc) * => HLI_JCOND (++si < 2) * Found in Turbo C. Intrinsic to C language. ****************************************************************************/ -static boolT idiom20 (iICODE picode, iICODE pend, Function * pproc) -{ boolT type = 0; /* type of variable: 1 = reg-var, 2 = local */ - byte regi; /* register of the MOV */ - - /* Get variable */ - if (picode->ic.ll.dst.regi == 0) /* global variable */ - /* not supported yet */ ; - else if (picode->ic.ll.dst.regi < INDEXBASE) /* register */ +struct Idiom20 : public Idiom +{ +protected: + iICODE m_icodes[4]; + bool m_is_dec; +public: + Idiom20(Function *f) : Idiom(f) { - if ((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR)) - type = 1; - else if ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR)) - type = 1; } - else if (picode->ic.ll.dst.off) /* local variable */ - type = 2; - else /* indexed */ - /* not supported yet */ ; - - /* Check previous instruction for a MOV */ - if (type == 1) /* register variable */ + uint8_t minimum_match_length() {return 4;} + bool match(iICODE picode) { - if ((picode < pend) && ((picode+1)->ic.ll.opcode == iMOV) && - ((picode+1)->ic.ll.src.regi == picode->ic.ll.dst.regi)) + uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */ + byte regi; /* register of the MOV */ + if(std::distance(picode,m_end)<3) + 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 */ { - regi = (picode+1)->ic.ll.dst.regi; - if ((regi > 0) && (regi < INDEXBASE)) + /* 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)) { - if (((picode+1) < pend) && ((picode+2) < pend) && - ((picode+2)->ic.ll.opcode == iCMP) && - ((picode+2)->ic.ll.dst.regi == regi) && - (((picode+3)->ic.ll.opcode >= iJB) && - ((picode+3)->ic.ll.opcode < iJCXZ))) - return true; + 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 ((picode < pend) && ((picode+1)->ic.ll.opcode == iMOV) && - ((picode+1)->ic.ll.src.off == picode->ic.ll.dst.off)) + else if (type == 2) /* local */ { - regi = (picode+1)->ic.ll.dst.regi; - if ((regi > 0) && (regi < INDEXBASE)) + if ( m_icodes[0]->ic.ll.match(iMOV) && + (m_icodes[1]->ic.ll.src.off == m_icodes[0]->ic.ll.dst.off)) { - if (((picode+1) < pend) && ((picode+2) < pend) && - ((picode+2)->ic.ll.opcode == iCMP) && - ((picode+2)->ic.ll.dst.regi == regi) && - (((picode+3)->ic.ll.opcode >= iJB) && - ((picode+3)->ic.ll.opcode < iJCXZ))) - return true; + 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; } - return false; -} - + int 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 3; + } +}; /***************************************************************************** * findIdioms - translates LOW_LEVEL icode idioms into HIGH_LEVEL icodes. ****************************************************************************/ void Function::findIdioms() { -// Int ip; /* Index to current icode */ + // Int ip; /* Index to current icode */ iICODE pEnd, pIcode; /* Pointers to end of BB and current icodes */ int16 delta; COND_EXPR *rhs, *lhs; /* Pointers to left and right hand side exps */ @@ -1066,324 +902,261 @@ void Function::findIdioms() pIcode = Icode.begin(); pEnd = Icode.end(); + Idiom1 i01(this); + Idiom2 i02(this); + Idiom3 i03(this); + Idiom4 i04(this); + Idiom17 i17(this); + Idiom18 i18(this); + Idiom19 i19(this); + Idiom20 i20(this); while (pIcode < pEnd) { switch (pIcode->ic.ll.opcode) { - case iDEC: case iINC: - if (idiom18 (pIcode, pEnd, this)) - { - 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); + case iDEC: case iINC: + if (i18.match(pIcode)) + pIcode += i18.action(); + else if (i20.match(pIcode)) + pIcode += i20.action(); + else if (i19.match(pIcode)) + pIcode += i19.action(); + else + pIcode++; + break; - (pIcode-1)->invalidate(); - pIcode->invalidate(); - (pIcode+1)->invalidate(); - pIcode += 3; - } - else if (idiom19 (pIcode, pEnd, this)) - { - lhs = COND_EXPR::id (*pIcode, DST, this, pIcode, *(pIcode+1), eUSE); - if (pIcode->ic.ll.opcode == iDEC) - lhs = COND_EXPR::unary (PRE_DEC, lhs); - else - lhs = COND_EXPR::unary (PRE_INC, lhs); - rhs = COND_EXPR::idKte (0, 2); - exp = COND_EXPR::boolOp (lhs, rhs, - condOpJCond[(pIcode+1)->ic.ll.opcode - iJB]); - (pIcode+1)->setJCond(exp); - pIcode->invalidate(); - pIcode += 2; - } - else if (idiom20 (pIcode, pEnd, this)) - { - lhs = COND_EXPR::id (*(pIcode+1), SRC, this, pIcode, *pIcode, eUSE); - if (pIcode->ic.ll.opcode == iDEC) - lhs = COND_EXPR::unary (PRE_DEC, lhs); - else - lhs = COND_EXPR::unary (PRE_INC, lhs); - rhs = COND_EXPR::id (*(pIcode+2), SRC, this, pIcode, *(pIcode+3), eUSE); - exp = COND_EXPR::boolOp (lhs, rhs, - condOpJCond[(pIcode+3)->ic.ll.opcode - iJB]); - (pIcode+3)->setJCond(exp); - pIcode->invalidate(); - (pIcode+1)->invalidate(); - (pIcode+2)->invalidate(); - pIcode += 3; - } - else - pIcode++; + case iPUSH: /* Idiom 1 */ + if(flg & PROC_HLL) // todo add other push idioms. + { + ++pIcode; break; + } + if (i01.match(pIcode)) + pIcode += i01.action(); + else + pIcode++; + break; - case iPUSH: /* Idiom 1 */ - if ((! (flg & PROC_HLL)) && (idx = idiom1 (pIcode, pEnd, this))) - { - flg |= PROC_HLL; - for ( ; idx > 0; idx--) - { - (pIcode++)->invalidate(); - } - } - else - pIcode++; - break; + case iMOV: /* Idiom 2 */ + if (i02.match(pIcode)) + { + pIcode += i02.action(); + } + else if (idiom14 (pIcode, pEnd, ®L, ®H)) /* Idiom 14 */ + { + idx = localId.newLongReg (TYPE_LONG_SIGN, regH, regL, pIcode/*ip*/); + lhs = COND_EXPR::idLongIdx (idx); + pIcode->setRegDU( regH, eDEF); + rhs = COND_EXPR::id (*pIcode, SRC, this, pIcode, *pIcode, NONE); + pIcode->setAsgn(lhs, rhs); + (pIcode+1)->invalidate(); + pIcode += 2; + } + else if (idx = idiom13 (pIcode, pEnd)) /* Idiom 13 */ + { + lhs = COND_EXPR::idReg (idx, 0, &localId); + pIcode->setRegDU( idx, eDEF); + pIcode->du1.numRegsDef--; /* prev byte reg def */ + rhs = COND_EXPR::id (*pIcode, SRC, this, pIcode, *pIcode, NONE); + pIcode->setAsgn(lhs, rhs); + (pIcode+1)->invalidate(); + pIcode += 2; + } + else + pIcode++; + break; - case iMOV: /* Idiom 2 */ - if (idx = idiom2(pIcode, pEnd, this)) - { - pIcode->invalidate(); - (pIcode+1)->invalidate(); - pIcode += 3; - } - else if (idiom14 (pIcode, pEnd, ®L, ®H)) /* Idiom 14 */ - { - idx = localId.newLongReg (TYPE_LONG_SIGN, regH, regL, pIcode/*ip*/); - lhs = COND_EXPR::idLongIdx (idx); - pIcode->setRegDU( regH, eDEF); - rhs = COND_EXPR::id (*pIcode, SRC, this, pIcode, *pIcode, NONE); - pIcode->setAsgn(lhs, rhs); - (pIcode+1)->invalidate(); - pIcode += 2; - } - else if (idx = idiom13 (pIcode, pEnd)) /* Idiom 13 */ - { - lhs = COND_EXPR::idReg (idx, 0, &localId); - pIcode->setRegDU( idx, eDEF); - pIcode->du1.numRegsDef--; /* prev byte reg def */ - rhs = COND_EXPR::id (*pIcode, SRC, this, pIcode, *pIcode, NONE); - pIcode->setAsgn(lhs, rhs); - (pIcode+1)->invalidate(); - pIcode += 2; - } - else - pIcode++; - break; - - case iCALL: case iCALLF: - /* Check for library functions that return a long register. + case iCALL: case iCALLF: + /* Check for library functions that return a long register. * Propagate this result */ - if (pIcode->ic.ll.src.proc.proc != 0) - if ((pIcode->ic.ll.src.proc.proc->flg & PROC_ISLIB) && + if (pIcode->ic.ll.src.proc.proc != 0) + if ((pIcode->ic.ll.src.proc.proc->flg & PROC_ISLIB) && (pIcode->ic.ll.src.proc.proc->flg & PROC_IS_FUNC)) - { - if ((pIcode->ic.ll.src.proc.proc->retVal.type==TYPE_LONG_SIGN) + { + if ((pIcode->ic.ll.src.proc.proc->retVal.type==TYPE_LONG_SIGN) || (pIcode->ic.ll.src.proc.proc->retVal.type == TYPE_LONG_UNSIGN)) - localId.newLongReg(TYPE_LONG_SIGN, rDX, rAX, pIcode/*ip*/); - } - - /* Check for idioms */ - if (idx = idiom3(pIcode, pEnd)) /* idiom 3 */ - { - if (pIcode->ic.ll.flg & I) - { - (pIcode->ic.ll.src.proc.proc)->cbParam = (int16)idx; - pIcode->ic.ll.src.proc.cb = idx; - (pIcode->ic.ll.src.proc.proc)->flg |= CALL_C; - pIcode++; - (pIcode++)->invalidate(); - } - else - { - printf("Indirect call at idiom3\n"); - pIcode++; - } + localId.newLongReg(TYPE_LONG_SIGN, rDX, rAX, pIcode/*ip*/); } - else if (idx = idiom17 (pIcode, pEnd)) /* idiom 17 */ - { - if (pIcode->isLlFlag(I)) - { - (pIcode->ic.ll.src.proc.proc)->cbParam = (int16)idx; - pIcode->ic.ll.src.proc.cb = idx; - (pIcode->ic.ll.src.proc.proc)->flg |= CALL_C; - //ip += 1; +1 is added out of switch - pIcode++; // skip call(f) - for (idx /= 2; idx > 0; idx--) - { - (pIcode++)->invalidate(); - } - } - // TODO : it's a calculated call - else - { - printf("Indirect call at idiom17\n"); - pIcode++; - } - } - else - pIcode++; - break; - case iRET: /* Idiom 4 */ - case iRETF: - idiom4 (pIcode, pEnd, this); + /* Check for idioms */ + if (i03.match(pIcode)) /* idiom 3 */ + { + pIcode+=i03.action(); + } + else if (i17.match(pIcode)) /* idiom 17 */ + { + pIcode+=i17.action(); + } + else pIcode++; - break; + break; - case iADD: /* Idiom 5 */ - if (idiom5 (pIcode, pEnd)) - { + case iRET: /* Idiom 4 */ + case iRETF: + if(i04.match(pIcode)) + i04.action(); + pIcode++; + break; - lhs = COND_EXPR::idLong (&localId, DST, pIcode, LOW_FIRST, + case iADD: /* Idiom 5 */ + if (idiom5 (pIcode, pEnd)) + { + + lhs = COND_EXPR::idLong (&localId, DST, pIcode, LOW_FIRST, pIcode/*ip*/, USE_DEF, 1); - rhs = COND_EXPR::idLong (&localId, SRC, pIcode, LOW_FIRST, + rhs = COND_EXPR::idLong (&localId, SRC, pIcode, LOW_FIRST, pIcode/*ip*/, eUSE, 1); - exp = COND_EXPR::boolOp (lhs, rhs, ADD); - pIcode->setAsgn(lhs, exp); - (pIcode+1)->invalidate(); - pIcode++; - } + exp = COND_EXPR::boolOp (lhs, rhs, ADD); + pIcode->setAsgn(lhs, exp); + (pIcode+1)->invalidate(); pIcode++; - break; + } + pIcode++; + break; - case iSAR: /* Idiom 8 */ - if (idiom8 (pIcode, pEnd)) - { - idx = localId.newLongReg(TYPE_LONG_SIGN, - pIcode->ic.ll.dst.regi, (pIcode+1)->ic.ll.dst.regi,pIcode/*ip*/); - lhs = COND_EXPR::idLongIdx (idx); - pIcode->setRegDU( (pIcode+1)->ic.ll.dst.regi, USE_DEF); - rhs = COND_EXPR::idKte (1, 2); - exp = COND_EXPR::boolOp (lhs, rhs, SHR); - pIcode->setAsgn(lhs, exp); - (pIcode+1)->invalidate(); - pIcode++; - } + case iSAR: /* Idiom 8 */ + if (idiom8 (pIcode, pEnd)) + { + idx = localId.newLongReg(TYPE_LONG_SIGN, + pIcode->ic.ll.dst.regi, (pIcode+1)->ic.ll.dst.regi,pIcode/*ip*/); + lhs = COND_EXPR::idLongIdx (idx); + pIcode->setRegDU( (pIcode+1)->ic.ll.dst.regi, USE_DEF); + rhs = COND_EXPR::idKte (1, 2); + exp = COND_EXPR::boolOp (lhs, rhs, SHR); + pIcode->setAsgn(lhs, exp); + (pIcode+1)->invalidate(); pIcode++; - break; + } + pIcode++; + break; - case iSHL: - if (idx = idiom15 (pIcode, pEnd)) /* idiom 15 */ - { - lhs = COND_EXPR::idReg (pIcode->ic.ll.dst.regi, + case iSHL: + if (idx = idiom15 (pIcode, pEnd)) /* idiom 15 */ + { + lhs = COND_EXPR::idReg (pIcode->ic.ll.dst.regi, pIcode->ic.ll.flg & NO_SRC_B, &localId); - rhs = COND_EXPR::idKte (idx, 2); - exp = COND_EXPR::boolOp (lhs, rhs, SHL); - pIcode->setAsgn(lhs, exp); - pIcode++; - for (idx-- ; idx > 0; idx--) - { - (pIcode++)->invalidate(); - } - } - else if (idiom12 (pIcode, pEnd)) /* idiom 12 */ - { - idx = localId.newLongReg (TYPE_LONG_UNSIGN, - (pIcode+1)->ic.ll.dst.regi, pIcode->ic.ll.dst.regi,pIcode/*ip*/); - lhs = COND_EXPR::idLongIdx (idx); - pIcode->setRegDU( (pIcode+1)->ic.ll.dst.regi, USE_DEF); - rhs = COND_EXPR::idKte (1, 2); - exp = COND_EXPR::boolOp (lhs, rhs, SHL); - pIcode->setAsgn(lhs, exp); - (pIcode+1)->invalidate(); - pIcode += 2; - } - else - pIcode++; - break; - - case iSHR: /* Idiom 9 */ - if (idiom9 (pIcode, pEnd)) - { - idx = localId.newLongReg (TYPE_LONG_UNSIGN, - pIcode->ic.ll.dst.regi, (pIcode+1)->ic.ll.dst.regi,pIcode/*ip*/); - lhs = COND_EXPR::idLongIdx (idx); - pIcode->setRegDU( (pIcode+1)->ic.ll.dst.regi, USE_DEF); - rhs = COND_EXPR::idKte (1, 2); - exp = COND_EXPR::boolOp (lhs, rhs, SHR); - pIcode->setAsgn(lhs, exp); - (pIcode+1)->invalidate(); - pIcode++; - } + rhs = COND_EXPR::idKte (idx, 2); + exp = COND_EXPR::boolOp (lhs, rhs, SHL); + pIcode->setAsgn(lhs, exp); pIcode++; - break; - - case iSUB: /* Idiom 6 */ - if (idiom6 (pIcode, pEnd)) + for (idx-- ; idx > 0; idx--) { - lhs = COND_EXPR::idLong (&localId, DST, pIcode, LOW_FIRST, pIcode, USE_DEF, 1); - rhs = COND_EXPR::idLong (&localId, SRC, pIcode, LOW_FIRST, pIcode, eUSE, 1); - exp = COND_EXPR::boolOp (lhs, rhs, SUB); - pIcode->setAsgn(lhs, exp); - (pIcode+1)->invalidate(); - pIcode++; + (pIcode++)->invalidate(); } + } + else if (idiom12 (pIcode, pEnd)) /* idiom 12 */ + { + idx = localId.newLongReg (TYPE_LONG_UNSIGN, + (pIcode+1)->ic.ll.dst.regi, pIcode->ic.ll.dst.regi,pIcode/*ip*/); + lhs = COND_EXPR::idLongIdx (idx); + pIcode->setRegDU( (pIcode+1)->ic.ll.dst.regi, USE_DEF); + rhs = COND_EXPR::idKte (1, 2); + exp = COND_EXPR::boolOp (lhs, rhs, SHL); + pIcode->setAsgn(lhs, exp); + (pIcode+1)->invalidate(); + pIcode += 2; + } + else pIcode++; - break; + break; - case iOR: /* Idiom 10 */ - idiom10 (pIcode, pEnd); + case iSHR: /* Idiom 9 */ + if (idiom9 (pIcode, pEnd)) + { + idx = localId.newLongReg (TYPE_LONG_UNSIGN, + pIcode->ic.ll.dst.regi, (pIcode+1)->ic.ll.dst.regi,pIcode/*ip*/); + lhs = COND_EXPR::idLongIdx (idx); + pIcode->setRegDU( (pIcode+1)->ic.ll.dst.regi, USE_DEF); + rhs = COND_EXPR::idKte (1, 2); + exp = COND_EXPR::boolOp (lhs, rhs, SHR); + pIcode->setAsgn(lhs, exp); + (pIcode+1)->invalidate(); pIcode++; - break; + } + pIcode++; + break; - case iNEG: /* Idiom 11 */ - if (idiom11 (pIcode, pEnd)) - { - lhs = COND_EXPR::idLong (&localId, DST, pIcode, HIGH_FIRST, + case iSUB: /* Idiom 6 */ + if (idiom6 (pIcode, pEnd)) + { + lhs = COND_EXPR::idLong (&localId, DST, pIcode, LOW_FIRST, pIcode, USE_DEF, 1); + rhs = COND_EXPR::idLong (&localId, SRC, pIcode, LOW_FIRST, pIcode, eUSE, 1); + exp = COND_EXPR::boolOp (lhs, rhs, SUB); + pIcode->setAsgn(lhs, exp); + (pIcode+1)->invalidate(); + pIcode++; + } + pIcode++; + break; + + case iOR: /* Idiom 10 */ + idiom10 (pIcode, pEnd); + pIcode++; + break; + + case iNEG: /* Idiom 11 */ + if (idiom11 (pIcode, pEnd)) + { + lhs = COND_EXPR::idLong (&localId, DST, pIcode, HIGH_FIRST, pIcode/*ip*/, USE_DEF, 1); - rhs = COND_EXPR::unary (NEGATION, lhs); - pIcode->setAsgn(lhs, rhs); - (pIcode+1)->invalidate(); - (pIcode+2)->invalidate(); - pIcode += 3; - } - else if (idiom16 (pIcode, pEnd)) - { - lhs = COND_EXPR::idReg (pIcode->ic.ll.dst.regi, pIcode->ic.ll.flg, + rhs = COND_EXPR::unary (NEGATION, lhs); + pIcode->setAsgn(lhs, rhs); + (pIcode+1)->invalidate(); + (pIcode+2)->invalidate(); + pIcode += 3; + } + else if (idiom16 (pIcode, pEnd)) + { + lhs = COND_EXPR::idReg (pIcode->ic.ll.dst.regi, pIcode->ic.ll.flg, &localId); - rhs = lhs->clone(); - rhs = COND_EXPR::unary (NEGATION, lhs); - pIcode->setAsgn(lhs, rhs); - (pIcode+1)->invalidate(); - (pIcode+2)->invalidate(); - pIcode += 3; - } - else - pIcode++; - break; - - case iNOP: - (pIcode++)->invalidate(); - break; - - case iENTER: /* ENTER is equivalent to init PUSH bp */ - if (pIcode == Icode.begin()) //ip == 0 - { - flg |= (PROC_HLL | PROC_IS_HLL); - } + rhs = lhs->clone(); + rhs = COND_EXPR::unary (NEGATION, lhs); + pIcode->setAsgn(lhs, rhs); + (pIcode+1)->invalidate(); + (pIcode+2)->invalidate(); + pIcode += 3; + } + else pIcode++; - break; + break; - case iXOR: /* Idiom 7 */ - if (idiom21 (pIcode, pEnd)) - { - lhs = COND_EXPR::idLong (&localId, DST, pIcode,HIGH_FIRST, pIcode/*ip*/, eDEF, 1); - rhs = COND_EXPR::idKte ((pIcode+1)->ic.ll.src.op() , 4); - pIcode->setAsgn(lhs, rhs); - pIcode->du.use = 0; /* clear register used in iXOR */ - (pIcode+1)->invalidate(); - pIcode++; - } - else if (idiom7 (pIcode)) - { - lhs = COND_EXPR::id (*pIcode, DST, this, pIcode, *pIcode, NONE); - rhs = COND_EXPR::idKte (0, 2); - pIcode->setAsgn(lhs, rhs); - pIcode->du.use = 0; /* clear register used in iXOR */ - pIcode->ic.ll.flg |= I; - } - pIcode++; - break; + case iNOP: + (pIcode++)->invalidate(); + break; - default: + case iENTER: /* ENTER is equivalent to init PUSH bp */ + if (pIcode == Icode.begin()) //ip == 0 + { + flg |= (PROC_HLL | PROC_IS_HLL); + } + pIcode++; + break; + + case iXOR: /* Idiom 7 */ + if (idiom21 (pIcode, pEnd)) + { + lhs = COND_EXPR::idLong (&localId, DST, pIcode,HIGH_FIRST, pIcode/*ip*/, eDEF, 1); + rhs = COND_EXPR::idKte ((pIcode+1)->ic.ll.src.op() , 4); + pIcode->setAsgn(lhs, rhs); + pIcode->du.use = 0; /* clear register used in iXOR */ + (pIcode+1)->invalidate(); pIcode++; + } + else if (idiom7 (pIcode)) + { + lhs = COND_EXPR::id (*pIcode, DST, this, pIcode, *pIcode, NONE); + rhs = COND_EXPR::idKte (0, 2); + pIcode->setAsgn(lhs, rhs); + pIcode->du.use = 0; /* clear register used in iXOR */ + pIcode->ic.ll.flg |= I; + } + pIcode++; + break; + + default: + pIcode++; } } @@ -1407,7 +1180,7 @@ void Function::bindIcodeOff() { Int i; /* idx into icode array */ iICODE pIcode; /* ptr icode array */ - dword *p,j; /* for case table */ + dword *p; /* for case table */ if (Icode.empty()) /* No Icode */ return; @@ -1417,37 +1190,37 @@ void Function::bindIcodeOff() for (i = 0; i < Icode.size(); i++) if ((pIcode[i].ic.ll.flg & I) && JmpInst(pIcode[i].ic.ll.opcode)) { - if (Icode.labelSrch(pIcode[i].ic.ll.src.op(), j)) - { - pIcode[j].ic.ll.flg |= TARGET; - } + iICODE loc=Icode.labelSrch(pIcode[i].ic.ll.src.op()); + if (loc!=Icode.end()) + loc->ic.ll.flg |= TARGET; } /* Finally bind jump targets to Icode offsets. Jumps for which no label * is found (no code at dest. of jump) are simply left unlinked and * flagged as going nowhere. */ - - for (pIcode = Icode.begin(); pIcode!= Icode.end(); pIcode++) - if (JmpInst(pIcode->ic.ll.opcode)) + //for (pIcode = Icode.begin(); pIcode!= Icode.end(); pIcode++) + for(ICODE &icode : Icode) + { + if (not JmpInst(icode.ic.ll.opcode)) + continue; + if (icode.ic.ll.flg & I) { - if (pIcode->ic.ll.flg & I) + dword found; + if (! Icode.labelSrch(icode.ic.ll.src.op(), found)) { - dword found; - if (! Icode.labelSrch(pIcode->ic.ll.src.op(), found)) - { - pIcode->ic.ll.flg |= NO_LABEL; - } - else - pIcode->ic.ll.src.SetImmediateOp(found); + icode.ic.ll.flg |= NO_LABEL; + } + else + icode.ic.ll.src.SetImmediateOp(found); - } - else if (pIcode->ic.ll.flg & SWITCH) - { - p = pIcode->ic.ll.caseTbl.entries; - for (j = 0; j < pIcode->ic.ll.caseTbl.numEntries; j++, p++) - Icode.labelSrch(*p, *p); - } } + else if (icode.ic.ll.flg & SWITCH) + { + p = icode.ic.ll.caseTbl.entries; + for (int j = 0; j < icode.ic.ll.caseTbl.numEntries; j++, p++) + Icode.labelSrch(*p, *p); + } + } } /* Performs idioms analysis, and propagates long operands, if any */ diff --git a/src/udm.cpp b/src/udm.cpp index 7e90ca9..9334b2d 100644 --- a/src/udm.cpp +++ b/src/udm.cpp @@ -18,16 +18,15 @@ static void displayDfs(BB * pBB); void Function::buildCFG() { if(flg & PROC_ISLIB) - return; /* Ignore library functions */ + return; // Ignore library functions createCFG(); if (option.VeryVerbose) displayCFG(); - /* Remove redundancies and add in-edge information */ - compressCFG(); - /* Print 2nd pass assembler listing */ + compressCFG(); // Remove redundancies and add in-edge information + if (option.asm2) - disassem(2, this); + disassem(2, this); // Print 2nd pass assembler listing /* Idiom analysis and propagation of long type */ lowLevelAnalysis();