home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / dosdisas.zip / dccsrcoo.zip / idioms.cpp < prev    next >
C/C++ Source or Header  |  1997-04-09  |  46KB  |  1,394 lines

  1. /*****************************************************************************
  2.  *$Log:    idioms.c,v $
  3.  * Revision 2.16  94/03/14  08:42:10  cifuente
  4.  * Type propagation is now part of another file (proplong.c).
  5.  * 
  6.  * Revision 2.15  94/02/22  17:03:08  cifuente
  7.  * Idiom 16 : logical negation.
  8.  * 
  9.  * Revision 2.14  94/02/22  15:17:01  cifuente
  10.  * New idioms and propagation of long variables.
  11.  * 
  12.  * Revision 2.13  93/12/13  15:41:49  cifuente
  13.  * Fixed bug in idiom17 that incremented opcode rather than pIcode.
  14.  * 
  15.  * Revision 2.12  93/12/13  12:21:44  cifuente
  16.  * Interprocedural live analysis finished.
  17.  * 
  18.  * Revision 2.11  93/11/10  17:27:31  cifuente
  19.  * Procedure header, locals
  20.  * 
  21.  * Revision 2.10  93/11/08  12:04:09  cifuente
  22.  * du1 analysis finished.  Instantiates procedure arguments for user
  23.  * declared procedures.
  24.  * 
  25.  * Revision 2.9  93/11/01  15:04:29  cifuente
  26.  * Finds byte and integer expressions
  27.  * 
  28.  * Revision 2.8  93/10/25  10:54:30  cifuente
  29.  * New SYNTHETIC instructions for d/u analysis
  30.  * 
  31.  * Revision 2.7  93/10/11  11:38:28  cifuente
  32.  * Introduced new idioms (idioms 5..11)
  33.  * First walk of HIGH_LEVEL icodes.
  34.  * 
  35.  * Revision 2.6  93/10/01  08:59:47  cifuente
  36.  * boolT type - for compilation under unix SVR4.2
  37.  * 
  38.  * Revision 2.5  93/09/29  10:44:52  cifuente
  39.  * LOW_LEVEL and HIGH_LEVEL icode definitions.  Increases llIcode indirection
  40.  * by 2 levels.
  41.  * 
  42.  * Revision 2.3  93/08/23  12:15:34  cifuente
  43.  * Interactive mode with curses
  44.  * 
  45.  * Revision 2.1  93/03/30  14:52:06  cifuente
  46.  * Compiled with gcc.
  47.  * 
  48.  *          REVCOMP project machine idiom recognition
  49.  ****************************************************************************/
  50.  
  51. #include "dcc.h"
  52. #include <string.h>
  53. #ifdef __DOSWIN__
  54. #include <stdio.h>
  55. #endif
  56.  
  57.  
  58. /*****************************************************************************
  59.  * JmpInst - Returns TRUE if opcode is a conditional or unconditional jump
  60.  ****************************************************************************/
  61. boolT JmpInst(llIcode opcode)
  62. {
  63.     switch (opcode) {
  64.         case iJMP:  case iJMPF: case iJCXZ:
  65.         case iLOOP: case iLOOPE:case iLOOPNE:
  66.         case iJB:   case iJBE:  case iJAE:  case iJA:
  67.         case iJL:   case iJLE:  case iJGE:  case iJG: 
  68.         case iJE:   case iJNE:  case iJS:   case iJNS:
  69.         case iJO:   case iJNO:  case iJP:   case iJNP:
  70.             return TRUE;
  71.     }
  72.     return FALSE;
  73. }
  74.  
  75.  
  76. /*****************************************************************************
  77. /* checkStkVars - Checks for PUSH SI
  78.  *                          [PUSH DI]
  79.  *                or         PUSH DI
  80.  *                          [PUSH SI]
  81.  * In which case, the stack variable flags are set 
  82.  ****************************************************************************/
  83. static Int checkStkVars (PICODE pIcode, PICODE pEnd, PPROC pProc)
  84. {
  85.     /* Look for PUSH SI */
  86.     if ((pIcode < pEnd) && (pIcode->ic.ll.opcode == iPUSH) &&
  87.         (pIcode->ic.ll.dst.regi == rSI))
  88.     {
  89.         pProc->flg |= SI_REGVAR;
  90.  
  91.         /* Look for PUSH DI */
  92.         if (++pIcode < pEnd && (pIcode->ic.ll.opcode == iPUSH) &&
  93.             (pIcode->ic.ll.dst.regi == rDI))
  94.         {
  95.             pProc->flg |= DI_REGVAR;    
  96.             return 2;
  97.         }
  98.         else
  99.             return 1;
  100.     }
  101.     else if ((pIcode < pEnd) && (pIcode->ic.ll.opcode == iPUSH) &&
  102.         (pIcode->ic.ll.dst.regi == rDI))
  103.     {
  104.         pProc->flg |= DI_REGVAR;
  105.  
  106.         /* Look for PUSH SI */
  107.         if ((++pIcode < pEnd) && (pIcode->ic.ll.opcode == iPUSH) &&
  108.             (pIcode->ic.ll.dst.regi == rSI))
  109.         {
  110.             pProc->flg |= SI_REGVAR;
  111.             return 2;
  112.         }
  113.         else
  114.             return 1;
  115.     }
  116.     else
  117.         return 0;
  118. }
  119.  
  120.  
  121. /*****************************************************************************
  122.  * idiom1 - HLL procedure prologue;  Returns number of instructions matched.
  123.  *          PUSH BP     ==> ENTER immed, 0
  124.  *          MOV  BP, SP     and sets PROC_HLL flag
  125.  *          [SUB  SP, immed]
  126.  *          [PUSH SI]
  127.  *          [PUSH DI]
  128.  *        - Second version: Push stack variables and then save BP
  129.  *          PUSH BP
  130.  *          PUSH SI
  131.  *          [PUSH DI]
  132.  *          MOV BP, SP
  133.  *        - Third version: Stack variables
  134.  *          [PUSH SI]
  135.  *          [PUSH DI]
  136.  ****************************************************************************/
  137. static Int idiom1(PICODE pIcode, PICODE pEnd, PPROC pProc)
  138. { Int n;
  139.  
  140.     /* PUSH BP as first instruction of procedure */
  141.     if ( !(pIcode->ic.ll.flg & I) && pIcode->ic.ll.src.regi == rBP)
  142.     {
  143.         /* MOV BP, SP as next instruction */
  144.         if (++pIcode < pEnd && ! (pIcode->ic.ll.flg & (I | TARGET | CASE))
  145.            && pIcode->ic.ll.opcode == iMOV && pIcode->ic.ll.dst.regi == rBP
  146.            && pIcode->ic.ll.src.regi == rSP)
  147.         {
  148.             pProc->args.minOff = 2;
  149.             pProc->flg |= PROC_IS_HLL;
  150.  
  151.             /* Look for SUB SP, immed */
  152.             if ((++pIcode < pEnd) &&
  153.                 (pIcode->ic.ll.flg & (I | TARGET | CASE)) == I &&
  154.                 pIcode->ic.ll.opcode == iSUB && pIcode->ic.ll.dst.regi == rSP)
  155.             {
  156.                 return (3 + checkStkVars (++pIcode, pEnd, pProc));
  157.             }
  158.             else
  159.                 return (2 + checkStkVars (pIcode, pEnd, pProc));
  160.         }
  161.  
  162.         /* PUSH SI
  163.          * [PUSH DI]
  164.          * MOV BP, SP */
  165.         else
  166.         {
  167.             n = checkStkVars (pIcode, pEnd, pProc);
  168.             if (n > 0)
  169.             {
  170.                 /* Look for MOV BP, SP */
  171.                 pIcode += n;
  172.                 if (pIcode < pEnd && 
  173.                     ! (pIcode->ic.ll.flg & (I | TARGET | CASE)) && 
  174.                     pIcode->ic.ll.opcode == iMOV && 
  175.                     pIcode->ic.ll.dst.regi == rBP && 
  176.                     pIcode->ic.ll.src.regi == rSP)
  177.                 {
  178.                     pProc->args.minOff = 2 + (n * 2);
  179.                     return (2 + n);
  180.                 }
  181.                 else return 0;        // Cristina: check this please!
  182.             }
  183.             else return 0;            // Cristina: check this please!
  184.         }
  185.     }
  186.  
  187.     else 
  188.         return (checkStkVars (pIcode, pEnd, pProc));
  189. }
  190.  
  191.  
  192. /*****************************************************************************
  193.  * popStkVars - checks for
  194.  *          [POP DI]
  195.  *          [POP SI]
  196.  *      or  [POP SI]
  197.  *          [POP DI]
  198.  ****************************************************************************/
  199. static void popStkVars (PICODE pIcode, PICODE pEnd, PPROC pProc)
  200. {
  201.     /* Match [POP DI] */
  202.     if (pIcode->ic.ll.opcode == iPOP)
  203.         if ((pProc->flg & DI_REGVAR) && (pIcode->ic.ll.dst.regi == rDI))
  204.             invalidateIcode (pIcode);
  205.         else if ((pProc->flg & SI_REGVAR) && (pIcode->ic.ll.dst.regi == rSI))
  206.             invalidateIcode (pIcode);
  207.  
  208.     /* Match [POP SI] */
  209.     if ((pIcode+1)->ic.ll.opcode == iPOP)
  210.         if ((pProc->flg & SI_REGVAR) && ((pIcode+1)->ic.ll.dst.regi == rSI))
  211.             invalidateIcode (pIcode+1);
  212.         else if ((pProc->flg & DI_REGVAR) && ((pIcode+1)->ic.ll.dst.regi == rDI))
  213.             invalidateIcode (pIcode+1);
  214. }
  215.  
  216.  
  217. /*****************************************************************************
  218.  * idiom2 - HLL procedure epilogue;  Returns number of instructions matched.
  219.  *          [POP DI]
  220.  *          [POP SI]
  221.  *          MOV  SP, BP 
  222.  *          POP  BP
  223.  *          RET(F)
  224.  *****************************************************************************/
  225. static Int idiom2(PICODE pIcode, PICODE pEnd, Int ip, PPROC pProc)
  226. { PICODE nicode;
  227.  
  228.     /* Match MOV SP, BP */
  229.     if (ip != 0 && ((pIcode->ic.ll.flg & I) != I) && 
  230.         pIcode->ic.ll.dst.regi == rSP && pIcode->ic.ll.src.regi == rBP)
  231.     {
  232.         /* Get next icode, skip over holes in the icode array */
  233.         nicode = pIcode + 1;
  234.         while (nicode->ic.ll.flg & NO_CODE)
  235.             nicode++;
  236.  
  237.         /* Match POP BP */
  238.         if (nicode < pEnd &&
  239.             ! (nicode->ic.ll.flg & (I | TARGET | CASE)) &&
  240.             nicode->ic.ll.opcode == iPOP && 
  241.             nicode->ic.ll.dst.regi == rBP)
  242.         {
  243.             nicode++;
  244.             
  245.             /* Match RET(F) */
  246.             if (nicode < pEnd &&
  247.                 ! (nicode->ic.ll.flg & (I | TARGET | CASE)) &&
  248.                 (nicode->ic.ll.opcode == iRET || 
  249.                 nicode->ic.ll.opcode == iRETF))
  250.             {
  251.                 popStkVars (pIcode-2, pEnd, pProc);
  252.                 return 2;
  253.             }
  254.         }
  255.     }
  256.     return 0;
  257. }
  258.  
  259.  
  260.  
  261. /*****************************************************************************
  262.  * idiom3 - C calling convention.
  263.  *          CALL(F)  proc_X
  264.  *          ADD  SP, immed
  265.  *      Eg: CALL proc_X
  266.  *          ADD  SP, 6
  267.  *          =>  pProc->cbParam = immed
  268.  *        Special case: when the call is at the end of the procedure, 
  269.  *                      sometimes the stack gets restored by a MOV sp, bp.
  270.  *                      Need to flag the procedure in these cases.
  271.  *  Used by compilers to restore the stack when invoking a procedure using
  272.  *  the C calling convention.
  273.  ****************************************************************************/
  274. static Int idiom3(PICODE pIcode, PICODE pEnd)
  275.     /* Match ADD  SP, immed */
  276.     if ((++pIcode < pEnd) && (pIcode->ic.ll.flg & I) &&
  277.         (pIcode->ic.ll.opcode == iADD) && (pIcode->ic.ll.dst.regi == rSP))
  278.         return (pIcode->ic.ll.immed.op);
  279.     else if ((pIcode->ic.ll.opcode == iMOV) && (pIcode->ic.ll.dst.regi == rSP)
  280.              && (pIcode->ic.ll.src.regi == rBP))
  281.         (pIcode-1)->ic.ll.flg |= REST_STK;
  282.     return 0;
  283. }
  284.  
  285.  
  286. /*****************************************************************************
  287.  * idiom 17 - C calling convention.
  288.  *          CALL(F)  xxxx
  289.  *          POP reg
  290.  *          [POP reg]           reg in {AX, BX, CX, DX}
  291.  *      Eg: CALL proc_X
  292.  *          POP cx
  293.  *          POP cx      (4 bytes of arguments)
  294.  *          => pProc->cbParam = # pops * 2
  295.  *  Found in Turbo C when restoring the stack for a procedure that uses the
  296.  *  C calling convention.  Used to restore the stack of 2 or 4 bytes args.
  297.  ****************************************************************************/
  298. static Int idiom17 (PICODE pIcode, PICODE pEnd)
  299. { Int i = 0;            /* Count on # pops */
  300.   byte regi;
  301.  
  302.     /* Match POP reg */
  303.     if ((++pIcode < pEnd) && (pIcode->ic.ll.opcode == iPOP))
  304.     {
  305.         regi = pIcode->ic.ll.dst.regi;
  306.         if ((regi >= rAX) && (regi <= rBX))
  307.             i++;
  308.         while ((++pIcode)->ic.ll.opcode == iPOP)
  309.         {
  310.             if (pIcode->ic.ll.dst.regi == regi)
  311.                 i++;
  312.             else
  313.                 break;
  314.         }
  315.         return (i * 2);
  316.     }
  317.     return (0);
  318. }
  319.  
  320.  
  321. /*****************************************************************************
  322.  * idiom4 - Pascal calling convention.
  323.  *          RET(F) immed   
  324.  *          ==> pProc->cbParam = immed
  325.  *              sets CALL_PASCAL flag 
  326.  *        - Second version: check for optional pop of stack vars
  327.  *          [POP DI]
  328.  *          [POP SI]
  329.  *          POP BP
  330.  *          RET(F) [immed]
  331.  *          - Third version: pop stack vars
  332.  *            [POP DI]
  333.  *            [POP SI]
  334.  *            RET(F) [immed]
  335.  ****************************************************************************/
  336. static void idiom4 (PICODE pIcode, PICODE pEnd, PPROC pProc)
  337. {
  338.     /* Check for [POP DI]
  339.      *           [POP SI] */
  340.     popStkVars (pIcode-3, pEnd, pProc);
  341.  
  342.     /* Check for POP BP */
  343.     if (((pIcode-1)->ic.ll.opcode == iPOP) && 
  344.         (((pIcode-1)->ic.ll.flg & I) != I) &&
  345.         ((pIcode-1)->ic.ll.dst.regi == rBP))
  346.         invalidateIcode (pIcode-1);
  347.     else
  348.         popStkVars (pIcode-2, pEnd, pProc);
  349.  
  350.     /* Check for RET(F) immed */
  351.     if (pIcode->ic.ll.flg & I) 
  352.     {
  353.         pProc->cbParam = (int16)pIcode->ic.ll.immed.op;
  354.         pProc->flg |= CALL_PASCAL;
  355.     }
  356. }
  357.  
  358.  
  359. /*****************************************************************************
  360.  * idiom5 - Long addition.
  361.  *      ADD reg/stackOff, reg/stackOff
  362.  *      ADC reg/stackOff, reg/stackOff 
  363.  *      Eg:     ADD ax, [bp-4]
  364.  *              ADC dx, [bp-2]
  365.  *          =>  dx:ax = dx:ax + [bp-2]:[bp-4]
  366.  *      Found in Borland Turbo C code.
  367.  *      Commonly used idiom for long addition.
  368.  ****************************************************************************/
  369. static boolT idiom5 (PICODE pIcode, PICODE pEnd)
  370. {
  371.     if (pIcode < pEnd)
  372.         if ((pIcode+1)->ic.ll.opcode == iADC)
  373.             return (TRUE);
  374.     return (FALSE);
  375. }
  376.  
  377.  
  378. /*****************************************************************************
  379.  * idiom6 - Long substraction.
  380.  *      SUB reg/stackOff, reg/stackOff
  381.  *      SBB reg/stackOff, reg/stackOff 
  382.  *      Eg:     SUB ax, [bp-4]
  383.  *              SBB dx, [bp-2]
  384.  *          =>  dx:ax = dx:ax - [bp-2]:[bp-4]
  385.  *      Found in Borland Turbo C code.
  386.  *      Commonly used idiom for long substraction.
  387.  ****************************************************************************/
  388. static boolT idiom6 (PICODE pIcode, PICODE pEnd)
  389. {
  390.     if (pIcode < pEnd)
  391.         if ((pIcode+1)->ic.ll.opcode == iSBB)
  392.             return (TRUE);
  393.     return (FALSE);
  394. }
  395.  
  396.  
  397. /*****************************************************************************
  398.  * idiom7 - Assign zero
  399.  *      XOR reg/stackOff, reg/stackOff
  400.  *      Eg:     XOR ax, ax
  401.  *          =>  ax = 0
  402.  *      Found in Borland Turbo C and Microsoft C code.
  403.  ****************************************************************************/
  404. static boolT idiom7 (PICODE pIcode)
  405. { PMEM dst, src;
  406.  
  407.     dst = &pIcode->ic.ll.dst;
  408.     src = &pIcode->ic.ll.src;
  409.     if (dst->regi == 0)                 /* global variable */
  410.     {
  411.         if ((dst->segValue == src->segValue) && (dst->off == src->off))
  412.             return (TRUE);
  413.     }
  414.     else if (dst->regi < INDEXBASE)     /* register */
  415.     {
  416.         if (dst->regi == src->regi)
  417.             return (TRUE);
  418.     }
  419.     else if ((dst->off) && (dst->seg == rSS) && (dst->regi == INDEXBASE + 6))
  420.                                         /* offset from BP */
  421.     {
  422.         if ((dst->off == src->off) && (dst->seg == src->seg) &&
  423.             (dst->regi == src->regi))
  424.             return (TRUE);
  425.     }
  426.     return (FALSE);
  427. }
  428.  
  429.  
  430. /*****************************************************************************
  431.  * idiom21 - Assign long kte with high part zero
  432.  *        XOR regH, regH
  433.  *        MOV regL, kte
  434.  *        => regH:regL = kte
  435.  *        Eg: XOR dx, dx
  436.  *            MOV ax, 3
  437.  *            => dx:ax = 3
  438.  *        Note: only the following valid combinations are available:
  439.  *                dx:ax
  440.  *                cx:bx
  441.  *        Found in Borland Turbo C code.
  442.  ****************************************************************************/
  443. static boolT idiom21 (PICODE picode, PICODE pend)
  444. { PMEM dst, src;
  445.  
  446.     dst = &picode->ic.ll.dst;
  447.     src = &picode->ic.ll.src;
  448.     if (((picode+1) < pend) && ((picode+1)->ic.ll.flg & I))
  449.     {
  450.         if ((dst->regi == src->regi) && (dst->regi > 0) && 
  451.             (dst->regi < INDEXBASE))
  452.         {
  453.             if ((dst->regi == rDX) && ((picode+1)->ic.ll.dst.regi == rAX))
  454.                 return (TRUE);
  455.             if ((dst->regi == rCX) && ((picode+1)->ic.ll.dst.regi == rBX))
  456.                 return (TRUE);
  457.         }
  458.     }
  459.     return (FALSE);
  460. }
  461.  
  462.  
  463. /*****************************************************************************
  464.  * idiom8 - Shift right by 1 (signed long ops)
  465.  *      SAR reg, 1
  466.  *      RCR reg, 1
  467.  *      Eg:     SAR dx, 1
  468.  *              RCR ax, 1
  469.  *          =>  dx:ax = dx:ax >> 1      (dx:ax are signed long)
  470.  *      Found in Microsoft C code for long signed variable shift right.
  471.  ****************************************************************************/
  472. static boolT idiom8 (PICODE pIcode, PICODE pEnd)
  473. {
  474.     if (pIcode < pEnd)
  475.     {
  476.         if (((pIcode->ic.ll.flg & I) == I) && (pIcode->ic.ll.immed.op == 1))
  477.             if (((pIcode+1)->ic.ll.opcode == iRCR) &&   
  478.                 (((pIcode+1)->ic.ll.flg & I) == I) && 
  479.                 ((pIcode+1)->ic.ll.immed.op == 1))
  480.                 return (TRUE);
  481.     }
  482.     return (FALSE);
  483. }
  484.  
  485.  
  486. /*****************************************************************************
  487.  * idiom 15 - Shift left by n 
  488.  *      SHL reg, 1
  489.  *      SHL reg, 1
  490.  *      [...]
  491.  *      [SHL    reg, 1]
  492.  *      Eg:     SHL ax, 1
  493.  *              SHL ax, 1
  494.  *          =>  ax = ax << 2
  495.  *      Found in Borland Turbo C code to index an array (array multiplication)
  496.  ****************************************************************************/
  497. static Int idiom15 (PICODE picode, PICODE pend)
  498. { Int n = 1; 
  499.   byte regi;
  500.  
  501.     if (picode < pend)
  502.     {
  503.         /* Match SHL reg, 1 */
  504.         if ((picode->ic.ll.flg & I) && (picode->ic.ll.immed.op == 1))
  505.         {
  506.             regi = picode->ic.ll.dst.regi;
  507.             while (1)
  508.             {
  509.                 if (((picode+n) < pend) &&
  510.                     ((picode+n)->ic.ll.opcode == iSHL) &&
  511.                     ((picode+n)->ic.ll.flg & I) && 
  512.                     ((picode+n)->ic.ll.immed.op == 1) &&
  513.                     ((picode+n)->ic.ll.dst.regi == regi))
  514.                     n++;
  515.                 else
  516.                     break;
  517.             }
  518.         }
  519.     }
  520.     if (n > 1)
  521.         return (n);
  522.     else
  523.         return (0);
  524. }
  525.  
  526.  
  527. /*****************************************************************************
  528.  * idiom12 - Shift left long by 1
  529.  *      SHL reg, 1
  530.  *      RCL reg, 1
  531.  *      Eg:     SHL ax, 1
  532.  *              RCL dx, 1
  533.  *          =>  dx:ax = dx:ax << 1
  534.  *      Found in Borland Turbo C code for long variable shift left.
  535.  ****************************************************************************/
  536. static boolT idiom12 (PICODE pIcode, PICODE pEnd)
  537. {
  538.     if (pIcode < pEnd)
  539.     {
  540.         if (((pIcode->ic.ll.flg & I) == I) && (pIcode->ic.ll.immed.op == 1))
  541.             if (((pIcode+1)->ic.ll.opcode == iRCL) &&   
  542.                 (((pIcode+1)->ic.ll.flg & I) == I) && 
  543.                 ((pIcode+1)->ic.ll.immed.op == 1))
  544.                 return (TRUE);
  545.     }
  546.     return (FALSE);
  547. }
  548.  
  549.  
  550. /*****************************************************************************
  551.  * idiom9 - Shift right by 1 (unsigned long ops)
  552.  *      SHR reg, 1
  553.  *      RCR reg, 1
  554.  *      Eg:     SHR dx, 1
  555.  *              RCR ax, 1
  556.  *          =>  dx:ax = dx:ax >> 1   (dx:ax are unsigned long)
  557.  *      Found in Microsoft C code for long unsigned variable shift right.
  558.  ****************************************************************************/
  559. static boolT idiom9 (PICODE pIcode, PICODE pEnd)
  560. {
  561.     if (pIcode < pEnd)
  562.     {
  563.         if (((pIcode->ic.ll.flg & I) == I) && (pIcode->ic.ll.immed.op == 1))
  564.             if (((pIcode+1)->ic.ll.opcode == iRCR) &&   
  565.                 (((pIcode+1)->ic.ll.flg & I) == I) && 
  566.                 ((pIcode+1)->ic.ll.immed.op == 1))
  567.                 return (TRUE);
  568.     }
  569.     return (FALSE);
  570. }
  571.  
  572.  
  573. /*****************************************************************************
  574.  * idiom10 - Jump if not equal to 0
  575.  *      OR  reg, reg
  576.  *      JNE labX
  577.  *      Eg:     OR  ax, ax
  578.  *              JNE labX
  579.  *      => HLI_JCOND (ax != 0) labX
  580.  *        Note: we also check that these instructions are not followed by
  581.  *              CMP reg, kte
  582.  *              JE  lab
  583.  *              because this is most likely a long conditional equality test.
  584.  *      Found in Borland Turbo C.
  585.  ****************************************************************************/
  586. static boolT idiom10old (PICODE pIcode, PICODE pEnd)
  587. {
  588.     if (pIcode < pEnd)
  589.     {
  590.         /* Check OR reg, reg */
  591.         if (((pIcode->ic.ll.flg & I) != I) && 
  592.             (pIcode->ic.ll.src. regi > 0) && 
  593.             (pIcode->ic.ll.src.regi < INDEXBASE) && 
  594.             (pIcode->ic.ll.src.regi == pIcode->ic.ll.dst.regi))
  595.             if ((pIcode+3) < pEnd)
  596.             {
  597.                 if (((pIcode+1)->ic.ll.opcode == iJNE) &&
  598.                     ((pIcode+2)->ic.ll.opcode != iCMP) &&
  599.                     ((pIcode+3)->ic.ll.opcode != iJE))
  600.                     return (TRUE);
  601.             }
  602.             else    /* at the end of the procedure */
  603.                 if (((pIcode+1) < pEnd) && ((pIcode+1)->ic.ll.opcode == iJNE))
  604.                     return (TRUE);
  605.     }
  606.     return (FALSE);
  607. }
  608.  
  609.  
  610. /*****************************************************************************
  611.  * idiom10 - Jump if not equal to 0
  612.  *      OR  reg, reg
  613.  *      JNE labX
  614.  *      Eg:     OR  ax, ax
  615.  *              JNE labX
  616.  *      => CMP reg 0
  617.  *           JNE labX
  618.  *        This instruction is NOT converted into the equivalent high-level
  619.  *        instruction "HLI_JCOND (reg != 0) labX" because we do not know yet if
  620.  *        it forms part of a long register conditional test.  It is therefore
  621.  *        modified to simplify the analysis.
  622.  *      Found in Borland Turbo C.
  623.  ****************************************************************************/
  624. static void idiom10 (PICODE pIcode, PICODE pEnd)
  625. {
  626.     if (pIcode < pEnd)
  627.     {
  628.         /* Check OR reg, reg */
  629.         if (((pIcode->ic.ll.flg & I) != I) && 
  630.             (pIcode->ic.ll.src. regi > 0) && 
  631.             (pIcode->ic.ll.src.regi < INDEXBASE) && 
  632.             (pIcode->ic.ll.src.regi == pIcode->ic.ll.dst.regi))
  633.             if (((pIcode+1) < pEnd) && ((pIcode+1)->ic.ll.opcode == iJNE))
  634.             {
  635.                 pIcode->ic.ll.opcode = iCMP;
  636.                 pIcode->ic.ll.flg |= I;
  637.                 pIcode->ic.ll.immed.op = 0;
  638.                 pIcode->du.def = 0;
  639.                 pIcode->du1.numRegsDef = 0;
  640.             }
  641.     }
  642. }
  643.  
  644.  
  645. /*****************************************************************************
  646.  * idiom 13 - Word assign
  647.  *      MOV regL, mem
  648.  *      MOV regH, 0
  649.  *      Eg:     MOV al, [bp-2]
  650.  *              MOV ah, 0
  651.  *      => MOV ax, [bp-2]
  652.  *      Found in Borland Turbo C, used for multiplication and division of
  653.  *      byte operands (ie. they need to be extended to words).
  654.  ****************************************************************************/
  655. static byte idiom13 (PICODE picode, PICODE pend)
  656. { byte regi;
  657.  
  658.     if (picode < pend)
  659.     {
  660.         /* Check for regL */
  661.         regi = picode->ic.ll.dst.regi;
  662.         if (((picode->ic.ll.flg & I) != I) && (regi >= rAL) && (regi <= rBH))
  663.         {
  664.             /* Check for MOV regH, 0 */
  665.             if (((picode+1)->ic.ll.opcode == iMOV) &&
  666.                 ((picode+1)->ic.ll.flg & I) &&
  667.                 ((picode+1)->ic.ll.immed.op == 0))
  668.             {
  669.                 if ((picode+1)->ic.ll.dst.regi == (regi + 4))
  670.                     return (regi - rAL + rAX);
  671.             }
  672.         }
  673.     }
  674.     return (0);
  675. }
  676.  
  677.  
  678. /*****************************************************************************
  679.  * idiom 14 - Long word assign
  680.  *      MOV regL, mem/reg
  681.  *      XOR regH, regH
  682.  *      Eg:     MOV ax, di 
  683.  *              XOR dx, dx
  684.  *      => MOV dx:ax, di 
  685.  *        Note: only the following combinations are allowed: 
  686.  *                dx:ax
  687.  *                cx:bx
  688.  *        this is to remove the possibility of making errors in situations
  689.  *        like this:
  690.  *            MOV dx, offH
  691.  *            MOV ax, offL
  692.  *            XOR    cx, cx
  693.  *      Found in Borland Turbo C, used for division of unsigned integer 
  694.  *      operands.
  695.  ****************************************************************************/
  696. static boolT idiom14 (PICODE picode, PICODE pend, byte *regL, byte *regH)
  697. {
  698.     if (picode < pend)
  699.     {
  700.         /* Check for regL */
  701.         *regL = picode->ic.ll.dst.regi;
  702.         if (((picode->ic.ll.flg & I) != I) && ((*regL == rAX) || (*regL ==rBX)))
  703.         {
  704.             /* Check for XOR regH, regH */
  705.             if (((picode+1)->ic.ll.opcode == iXOR) &&
  706.                 (((picode+1)->ic.ll.flg & I) != I)) 
  707.             {
  708.                 *regH = (picode+1)->ic.ll.dst.regi;
  709.                 if (*regH == (picode+1)->ic.ll.src.regi)
  710.                 {
  711.                     if ((*regL == rAX) && (*regH == rDX))
  712.                         return (TRUE);
  713.                     if ((*regL == rBX) && (*regH == rCX))
  714.                         return (TRUE);
  715.                 }
  716.             }
  717.         }
  718.     }
  719.     return (FALSE);
  720. }
  721.  
  722. /*****************************************************************************
  723.  * idiom11 - Negate long integer
  724.  *      NEG regH
  725.  *      NEG regL
  726.  *      SBB regH, 0
  727.  *      Eg:     NEG dx
  728.  *              NEG ax
  729.  *              SBB dx, 0
  730.  *      => dx:ax = - dx:ax
  731.  *      Found in Borland Turbo C.
  732.  ****************************************************************************/
  733. static boolT idiom11 (PICODE pIcode, PICODE pEnd)
  734. { condId type;          /* type of argument */
  735.  
  736.     if ((pIcode + 2) < pEnd)
  737.     {
  738.         type = idType  (pIcode, DST);
  739.         if ((type != CONSTANT) && (type != OTHER))
  740.         {
  741.             /* Check NEG reg/mem 
  742.              *       SBB reg/mem, 0*/
  743.             if (((pIcode+1)->ic.ll.opcode == iNEG) &&
  744.                 ((pIcode+2)->ic.ll.opcode == iSBB))
  745.                 switch (type) {
  746.                   case GLOB_VAR:    if (((pIcode+2)->ic.ll.dst.segValue ==
  747.                                         pIcode->ic.ll.dst.segValue) &&
  748.                                         ((pIcode+2)->ic.ll.dst.off ==
  749.                                         pIcode->ic.ll.dst.off))
  750.                                         return (TRUE);
  751.                                     break;
  752.                   case REGISTER:    if ((pIcode+2)->ic.ll.dst.regi ==
  753.                                         pIcode->ic.ll.dst.regi)
  754.                                         return (TRUE);
  755.                                     break;
  756.                   case PARAM:
  757.                   case LOCAL_VAR:   if ((pIcode+2)->ic.ll.dst.off ==
  758.                                         pIcode->ic.ll.dst.off)
  759.                                         return (TRUE);
  760.                                     break;
  761.                 }
  762.         }
  763.     }
  764.     return (FALSE);
  765. }
  766.  
  767.  
  768. /*****************************************************************************
  769.  * idiom 16: Bitwise negation
  770.  *        NEG reg
  771.  *        SBB reg, reg
  772.  *        INC reg
  773.  *        => ASGN reg, !reg
  774.  *        Eg:        NEG ax
  775.  *                SBB ax, ax
  776.  *                INC ax
  777.  *            => ax = !ax
  778.  *        Found in Borland Turbo C when negating bitwise.
  779.  ****************************************************************************/
  780. static boolT idiom16 (PICODE picode, PICODE pend)
  781. { byte regi;
  782.  
  783.     if ((picode+2) < pend)
  784.     {
  785.         regi = picode->ic.ll.dst.regi;
  786.         if ((regi >= rAX) && (regi < INDEXBASE))
  787.         {
  788.             if (((picode+1)->ic.ll.opcode == iSBB) &&
  789.                 ((picode+2)->ic.ll.opcode == iINC))
  790.                 if (((picode+1)->ic.ll.dst.regi == 
  791.                                             ((picode+1)->ic.ll.src.regi)) &&
  792.                     ((picode+1)->ic.ll.dst.regi == regi) &&
  793.                     ((picode+2)->ic.ll.dst.regi == regi))
  794.                     return (TRUE);
  795.         }
  796.     }
  797.     return (FALSE);
  798. }
  799.  
  800.  
  801. /*****************************************************************************
  802.  * idiom 18: Post-increment or post-decrement in a conditional jump
  803.  *        MOV  reg, var (including register variables)
  804.  *        INC     var    or DEC var
  805.  *        CMP  var, Y
  806.  *        JX   label
  807.  *        => HLI_JCOND (var++ X Y)
  808.  *        Eg:        MOV  ax, si
  809.  *                INC  si
  810.  *                CMP  ax, 8
  811.  *                JL   labX
  812.  *            =>  HLI_JCOND (si++ < 8)
  813.  *         Found in Borland Turbo C.  Intrinsic to C languages.
  814.  ****************************************************************************/
  815. static boolT idiom18 (PICODE picode, PICODE pend, PPROC pproc)
  816. { boolT type = 0;    /* type of variable: 1 = reg-var, 2 = local */
  817.   byte regi;        /* register of the MOV */
  818.  
  819.     /* Get variable */
  820.     if (picode->ic.ll.dst.regi == 0)    /* global variable */
  821.         /* not supported yet */ ;
  822.     else if (picode->ic.ll.dst.regi < INDEXBASE)    /* register */
  823.     {
  824.         if ((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR))
  825.             type = 1;
  826.         else if ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR))
  827.             type = 1;
  828.     }
  829.     else if (picode->ic.ll.dst.off)        /* local variable */
  830.         type = 2;
  831.     else        /* indexed */
  832.         /* not supported yet */ ;
  833.  
  834.     /* Check previous instruction for a MOV */
  835.     if (type == 1)            /* register variable */
  836.     {
  837.         if (((picode-1)->ic.ll.opcode == iMOV) &&
  838.             ((picode-1)->ic.ll.src.regi == picode->ic.ll.dst.regi))
  839.         {
  840.             regi = (picode-1)->ic.ll.dst.regi;
  841.             if ((regi > 0) && (regi < INDEXBASE))
  842.             {
  843.                 if ((picode < pend) && ((picode+1) < pend) &&
  844.                     ((picode+1)->ic.ll.opcode == iCMP) &&
  845.                     ((picode+1)->ic.ll.dst.regi == regi) &&
  846.                     (((picode+2)->ic.ll.opcode >= iJB) &&
  847.                      ((picode+2)->ic.ll.opcode < iJCXZ)))
  848.                     return (TRUE);
  849.             }
  850.         }
  851.     }
  852.     else if (type == 2)        /* local */
  853.     {
  854.         if (((picode-1)->ic.ll.opcode == iMOV) && 
  855.             ((picode-1)->ic.ll.src.off == picode->ic.ll.dst.off))
  856.         {
  857.             regi = (picode-1)->ic.ll.dst.regi;
  858.             if ((regi > 0) && (regi < INDEXBASE))
  859.             {
  860.                 if ((picode < pend) && ((picode+1) < pend) &&
  861.                     ((picode+1)->ic.ll.opcode == iCMP) &&
  862.                     ((picode+1)->ic.ll.dst.regi == regi) &&
  863.                     (((picode+2)->ic.ll.opcode >= iJB) && 
  864.                      ((picode+2)->ic.ll.opcode < iJCXZ)))
  865.                     return (TRUE);
  866.             }
  867.         }
  868.     }
  869.     return (FALSE);
  870. }
  871.  
  872.  
  873. /*****************************************************************************
  874.  * idiom 19: pre-increment or pre-decrement in conditional jump, comparing
  875.  *             against 0.
  876.  *        INC var            or DEC var        (including register vars)
  877.  *        JX    lab               JX  lab
  878.  *        =>  HLI_JCOND (++var X 0) or HLI_JCOND (--var X 0)
  879.  *        Eg: INC [bp+4]
  880.  *            JG  lab2
  881.  *            => HLI_JCOND (++[bp+4] > 0)
  882.  *        Found in Borland Turbo C.  Intrinsic to C language.
  883.  ****************************************************************************/
  884. static boolT idiom19 (PICODE picode, PICODE pend, PPROC pproc)
  885. {
  886.     if (picode->ic.ll.dst.regi == 0)    /* global variable */
  887.         /* not supported yet */ ;
  888.     else if (picode->ic.ll.dst.regi < INDEXBASE) /* register */
  889.     {
  890.         if (((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR)) ||
  891.             ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR)))
  892.             if ((picode < pend) && ((picode+1)->ic.ll.opcode >= iJB) && 
  893.                 ((picode+1)->ic.ll.opcode < iJCXZ))
  894.                 return (TRUE);
  895.     }
  896.     else if (picode->ic.ll.dst.off)        /* stack variable */
  897.     {
  898.         if ((picode < pend) && ((picode+1)->ic.ll.opcode >= iJB) && 
  899.             ((picode+1)->ic.ll.opcode < iJCXZ))
  900.             return (TRUE);
  901.     }
  902.     else    /* indexed */
  903.         /* not supported yet */ ;
  904.     return (FALSE);
  905. }
  906.  
  907.  
  908. /*****************************************************************************
  909.  * idiom20: Pre increment/decrement in conditional expression (compares
  910.  *            against a register, variable or constant different than 0).
  911.  *        INC var            or DEC var (including register vars)
  912.  *        MOV reg, var       MOV reg, var
  913.  *        CMP reg, Y           CMP reg, Y
  914.  *        JX  lab               JX  lab
  915.  *        => HLI_JCOND (++var X Y) or HLI_JCOND (--var X Y)
  916.  *        Eg: INC si    (si is a register variable)
  917.  *            MOV ax, si
  918.  *            CMP ax, 2
  919.  *            JL    lab4
  920.  *            => HLI_JCOND (++si < 2)
  921.  *        Found in Turbo C.  Intrinsic to C language.
  922.  ****************************************************************************/
  923. static boolT idiom20 (PICODE picode, PICODE pend, PPROC pproc)
  924. { boolT type = 0;    /* type of variable: 1 = reg-var, 2 = local */
  925.   byte regi;        /* register of the MOV */
  926.  
  927.     /* Get variable */
  928.     if (picode->ic.ll.dst.regi == 0)    /* global variable */
  929.         /* not supported yet */ ;
  930.     else if (picode->ic.ll.dst.regi < INDEXBASE)    /* register */
  931.     {
  932.         if ((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR))
  933.             type = 1;
  934.         else if ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR))
  935.             type = 1;
  936.     }
  937.     else if (picode->ic.ll.dst.off)        /* local variable */
  938.         type = 2;
  939.     else        /* indexed */
  940.         /* not supported yet */ ;
  941.  
  942.     /* Check previous instruction for a MOV */
  943.     if (type == 1)            /* register variable */
  944.     {
  945.         if ((picode < pend) && ((picode+1)->ic.ll.opcode == iMOV) && 
  946.             ((picode+1)->ic.ll.src.regi == picode->ic.ll.dst.regi))
  947.         {
  948.             regi = (picode+1)->ic.ll.dst.regi;
  949.             if ((regi > 0) && (regi < INDEXBASE))
  950.             {
  951.                 if (((picode+1) < pend) && ((picode+2) < pend) &&
  952.                     ((picode+2)->ic.ll.opcode == iCMP) &&
  953.                     ((picode+2)->ic.ll.dst.regi == regi) &&
  954.                     (((picode+3)->ic.ll.opcode >= iJB) && 
  955.                      ((picode+3)->ic.ll.opcode < iJCXZ)))
  956.                     return (TRUE);
  957.             }
  958.         }
  959.     }
  960.     else if (type == 2)        /* local */
  961.     {
  962.         if ((picode < pend) && ((picode+1)->ic.ll.opcode == iMOV) && 
  963.             ((picode+1)->ic.ll.src.off == picode->ic.ll.dst.off))
  964.         {
  965.             regi = (picode+1)->ic.ll.dst.regi;
  966.             if ((regi > 0) && (regi < INDEXBASE))
  967.             {
  968.                 if (((picode+1) < pend) && ((picode+2) < pend) &&
  969.                     ((picode+2)->ic.ll.opcode == iCMP) &&
  970.                     ((picode+2)->ic.ll.dst.regi == regi) &&
  971.                     (((picode+3)->ic.ll.opcode >= iJB) && 
  972.                      ((picode+3)->ic.ll.opcode < iJCXZ)))
  973.                     return (TRUE);
  974.             }
  975.         }
  976.     }
  977.     return (FALSE);
  978. }
  979.  
  980.  
  981. /*****************************************************************************
  982.  * findIdioms  - translates LOW_LEVEL icode idioms into HIGH_LEVEL icodes.
  983.  ****************************************************************************/
  984. void findIdioms (PPROC pProc)
  985. {   Int     ip;             /* Index to current icode                   */
  986.     PICODE  pEnd, pIcode;   /* Pointers to end of BB and current icodes */
  987.     int16   delta;
  988.     COND_EXPR *rhs, *lhs;   /* Pointers to left and right hand side exps */
  989.     COND_EXPR *exp;         /* Pointer to temporal expression           */
  990.     Int     idx;            /* Index into local identifier table        */
  991.     byte    regH, regL;     /* High and low registers for long word reg */
  992.  
  993.     pIcode = pProc->Icode.GetFirstIcode();
  994.     pEnd = pIcode + pProc->Icode.GetNumIcodes();
  995.     ip = 0;
  996.  
  997.     while (pIcode < pEnd)
  998.     {
  999.         switch (pIcode->ic.ll.opcode) {
  1000.         case iDEC: case iINC:
  1001.             if (idiom18 (pIcode, pEnd, pProc))
  1002.             {
  1003.                 lhs = idCondExp (pIcode-1, SRC, pProc, ip, pIcode, E_USE);
  1004.                 if (pIcode->ic.ll.opcode == iDEC)
  1005.                     lhs = unaryCondExp (POST_DEC, lhs);
  1006.                 else
  1007.                     lhs = unaryCondExp (POST_INC, lhs);
  1008.                 rhs = idCondExp (pIcode+1, SRC, pProc, ip, pIcode+2, E_USE);
  1009.                 exp = boolCondExp (lhs, rhs,
  1010.                                    condOpJCond[(pIcode+2)->ic.ll.opcode - iJB]);
  1011.                 newJCondHlIcode (pIcode+2, exp);
  1012.                 invalidateIcode (pIcode-1);
  1013.                 invalidateIcode (pIcode);
  1014.                 invalidateIcode (pIcode+1);
  1015.                 pIcode += 3;
  1016.                 ip += 2;
  1017.             }
  1018.             else if (idiom19 (pIcode, pEnd, pProc))
  1019.             {
  1020.                 lhs = idCondExp (pIcode, DST, pProc, ip, pIcode+1, E_USE);
  1021.                 if (pIcode->ic.ll.opcode == iDEC)
  1022.                     lhs = unaryCondExp (PRE_DEC, lhs);
  1023.                 else
  1024.                     lhs = unaryCondExp (PRE_INC, lhs);
  1025.                 rhs = idCondExpKte (0, 2);
  1026.                 exp = boolCondExp (lhs, rhs,
  1027.                                    condOpJCond[(pIcode+1)->ic.ll.opcode - iJB]);
  1028.                 newJCondHlIcode (pIcode+1, exp);
  1029.                 invalidateIcode (pIcode);
  1030.                 pIcode += 2;
  1031.                 ip++;
  1032.             }
  1033.             else if (idiom20 (pIcode, pEnd, pProc))
  1034.             {
  1035.                 lhs = idCondExp (pIcode+1, SRC, pProc, ip, pIcode, E_USE);
  1036.                 if (pIcode->ic.ll.opcode == iDEC)
  1037.                     lhs = unaryCondExp (PRE_DEC, lhs);
  1038.                 else
  1039.                     lhs = unaryCondExp (PRE_INC, lhs);
  1040.                 rhs = idCondExp (pIcode+2, SRC, pProc, ip, pIcode+3, E_USE);
  1041.                 exp = boolCondExp (lhs, rhs,
  1042.                                    condOpJCond[(pIcode+3)->ic.ll.opcode - iJB]);
  1043.                 newJCondHlIcode (pIcode+3, exp);
  1044.                 invalidateIcode (pIcode);
  1045.                 invalidateIcode (pIcode+1);
  1046.                 invalidateIcode (pIcode+2);
  1047.                 pIcode += 3;
  1048.                 ip += 2;
  1049.             }
  1050.             else
  1051.                 pIcode++;
  1052.             break;
  1053.  
  1054.         case iPUSH:             /* Idiom 1 */
  1055.             if ((! (pProc->flg & PROC_HLL)) && 
  1056.                 (idx = idiom1 (pIcode, pEnd, pProc)))
  1057.             {
  1058.                 pProc->flg |= PROC_HLL;
  1059.                 for ( ; idx > 0; idx--)
  1060.                 {
  1061.                     invalidateIcode (pIcode++);
  1062.                     ip++;
  1063.                 }
  1064.                 ip--;
  1065.             }
  1066.             else
  1067.                 pIcode++;
  1068.             break;
  1069.  
  1070.         case iMOV:              /* Idiom 2 */
  1071.             if (idx = idiom2(pIcode, pEnd, ip, pProc))
  1072.             {
  1073.                 invalidateIcode (pIcode);
  1074.                 invalidateIcode (pIcode+1);
  1075.                 pIcode += 3;
  1076.                 ip += 2;
  1077.             }
  1078.             else if (idiom14 (pIcode, pEnd, ®L, ®H))  /* Idiom 14 */ 
  1079.             {
  1080.                 idx = newLongRegId (&pProc->localId, TYPE_LONG_SIGN,
  1081.                                      regH, regL, ip);
  1082.                 lhs = idCondExpLongIdx (idx);
  1083.                 setRegDU (pIcode, regH, E_DEF);
  1084.                 rhs = idCondExp (pIcode, SRC, pProc, ip, pIcode, NONE);
  1085.                 newAsgnHlIcode (pIcode, lhs, rhs);
  1086.                 invalidateIcode (pIcode+1);
  1087.                 pIcode += 2;
  1088.                 ip++;
  1089.             }
  1090.             else if (idx = idiom13 (pIcode, pEnd))      /* Idiom 13 */ 
  1091.             {
  1092.                 lhs = idCondExpReg (idx, 0, &pProc->localId);
  1093.                 setRegDU (pIcode, idx, E_DEF);
  1094.                 pIcode->du1.numRegsDef--;       /* prev byte reg def */
  1095.                 rhs = idCondExp (pIcode, SRC, pProc, ip, pIcode, NONE);
  1096.                 newAsgnHlIcode (pIcode, lhs, rhs);
  1097.                 invalidateIcode (pIcode+1);
  1098.                 pIcode += 2;
  1099.                 ip++;
  1100.             } 
  1101.             else
  1102.                 pIcode++;
  1103.             break;
  1104.  
  1105.         case iCALL:  case iCALLF:
  1106.             /* Check for library functions that return a long register.
  1107.              * Propagate this result */
  1108.     if (pIcode->ic.ll.immed.proc.proc != 0)
  1109.             if ((pIcode->ic.ll.immed.proc.proc->flg & PROC_ISLIB) &&
  1110.                 (pIcode->ic.ll.immed.proc.proc->flg & PROC_IS_FUNC))
  1111.             {
  1112.                if ((pIcode->ic.ll.immed.proc.proc->retVal.type==TYPE_LONG_SIGN)    
  1113.                   || (pIcode->ic.ll.immed.proc.proc->retVal.type ==
  1114.                                                               TYPE_LONG_UNSIGN))
  1115.                     newLongRegId(&pProc->localId, TYPE_LONG_SIGN, rDX, rAX, ip);
  1116.             }
  1117.  
  1118.             /* Check for idioms */
  1119.             if (idx = idiom3(pIcode, pEnd))         /* idiom 3 */
  1120.             {
  1121.                 if (pIcode->ic.ll.flg & I) 
  1122.                 {
  1123.                     (pIcode->ic.ll.immed.proc.proc)->cbParam = (int16)idx;
  1124.                     pIcode->ic.ll.immed.proc.cb = idx;
  1125.                     (pIcode->ic.ll.immed.proc.proc)->flg |= CALL_C;
  1126.                     pIcode++;
  1127.                     invalidateIcode (pIcode++);
  1128.                     ip++;
  1129.                 }
  1130.             }
  1131.             else if (idx = idiom17 (pIcode, pEnd))  /* idiom 17 */
  1132.             {
  1133.                 if (pIcode->ic.ll.flg & I)
  1134.                 {
  1135.                     (pIcode->ic.ll.immed.proc.proc)->cbParam = (int16)idx;
  1136.                     pIcode->ic.ll.immed.proc.cb = idx;
  1137.                     (pIcode->ic.ll.immed.proc.proc)->flg |= CALL_C;
  1138.                     ip += idx/2 - 1;
  1139.                     pIcode++;
  1140.                     for (idx /= 2; idx > 0; idx--)
  1141.                         invalidateIcode (pIcode++);
  1142.                 }
  1143.             }
  1144.             else
  1145.                 pIcode++;
  1146.             break;
  1147.  
  1148.         case iRET:          /* Idiom 4 */   
  1149.         case iRETF:
  1150.             idiom4 (pIcode, pEnd, pProc);
  1151.             pIcode++;
  1152.             break;
  1153.  
  1154.         case iADD:          /* Idiom 5 */
  1155.             if (idiom5 (pIcode, pEnd))
  1156.             {
  1157.                 lhs = idCondExpLong (&pProc->localId, DST, pIcode, LOW_FIRST, 
  1158.                                      ip, USE_DEF, 1); 
  1159.                 rhs = idCondExpLong (&pProc->localId, SRC, pIcode, LOW_FIRST, 
  1160.                                      ip, E_USE, 1);
  1161.                 exp = boolCondExp (lhs, rhs, ADD);
  1162.                 newAsgnHlIcode (pIcode, lhs, exp);
  1163.                 invalidateIcode (pIcode + 1);
  1164.                 pIcode++;
  1165.                 ip++;
  1166.             }
  1167.             pIcode++;
  1168.             break;
  1169.  
  1170.         case iSAR:          /* Idiom 8 */
  1171.             if (idiom8 (pIcode, pEnd))
  1172.             {
  1173.                 idx = newLongRegId (&pProc->localId, TYPE_LONG_SIGN,
  1174.                         pIcode->ic.ll.dst.regi, (pIcode+1)->ic.ll.dst.regi,ip);
  1175.                 lhs = idCondExpLongIdx (idx);
  1176.                 setRegDU (pIcode, (pIcode+1)->ic.ll.dst.regi, USE_DEF);
  1177.                 rhs = idCondExpKte (1, 2);
  1178.                 exp = boolCondExp (lhs, rhs, SHR);
  1179.                 newAsgnHlIcode (pIcode, lhs, exp);
  1180.                 invalidateIcode (pIcode + 1);
  1181.                 pIcode++;
  1182.                 ip++;
  1183.             }
  1184.             pIcode++;
  1185.             break;
  1186.  
  1187.         case iSHL:
  1188.             if (idx = idiom15 (pIcode, pEnd))       /* idiom 15 */
  1189.             {
  1190.                 lhs = idCondExpReg (pIcode->ic.ll.dst.regi, 
  1191.                                     pIcode->ic.ll.flg & NO_SRC_B,
  1192.                                     &pProc->localId);
  1193.                 rhs = idCondExpKte (idx, 2);
  1194.                 exp = boolCondExp (lhs, rhs, SHL);
  1195.                 newAsgnHlIcode (pIcode, lhs, exp);
  1196.                 pIcode++;
  1197.                 for (idx-- ; idx > 0; idx--)
  1198.                 {
  1199.                     invalidateIcode (pIcode++);
  1200.                     ip++;
  1201.                 }
  1202.             }
  1203.             else if (idiom12 (pIcode, pEnd))        /* idiom 12 */
  1204.             {
  1205.                 idx = newLongRegId (&pProc->localId, TYPE_LONG_UNSIGN,
  1206.                         (pIcode+1)->ic.ll.dst.regi, pIcode->ic.ll.dst.regi,ip);
  1207.                 lhs = idCondExpLongIdx (idx);
  1208.                 setRegDU (pIcode, (pIcode+1)->ic.ll.dst.regi, USE_DEF);
  1209.                 rhs = idCondExpKte (1, 2);
  1210.                 exp = boolCondExp (lhs, rhs, SHL);
  1211.                 newAsgnHlIcode (pIcode, lhs, exp);
  1212.                 invalidateIcode (pIcode + 1);
  1213.                 pIcode += 2;
  1214.                 ip++;
  1215.             }
  1216.             else
  1217.                 pIcode++;
  1218.             break;
  1219.  
  1220.         case iSHR:          /* Idiom 9 */
  1221.             if (idiom9 (pIcode, pEnd))
  1222.             {
  1223.                 idx = newLongRegId (&pProc->localId, TYPE_LONG_UNSIGN,
  1224.                         pIcode->ic.ll.dst.regi, (pIcode+1)->ic.ll.dst.regi,ip);
  1225.                 lhs = idCondExpLongIdx (idx);
  1226.                 setRegDU (pIcode, (pIcode+1)->ic.ll.dst.regi, USE_DEF);
  1227.                 rhs = idCondExpKte (1, 2);
  1228.                 exp = boolCondExp (lhs, rhs, SHR);
  1229.                 newAsgnHlIcode (pIcode, lhs, exp);
  1230.                 invalidateIcode (pIcode + 1);
  1231.                 pIcode++;
  1232.                 ip++;
  1233.             }
  1234.             pIcode++;
  1235.             break;
  1236.  
  1237.         case iSUB:          /* Idiom 6 */
  1238.             if (idiom6 (pIcode, pEnd))
  1239.             {
  1240.                 lhs = idCondExpLong (&pProc->localId, DST, pIcode, LOW_FIRST, 
  1241.                                      ip, USE_DEF, 1);
  1242.                 rhs = idCondExpLong (&pProc->localId, SRC, pIcode, LOW_FIRST, 
  1243.                                      ip, E_USE, 1);
  1244.                 exp = boolCondExp (lhs, rhs, SUB);
  1245.                 newAsgnHlIcode (pIcode, lhs, exp);
  1246.                 invalidateIcode (pIcode + 1);
  1247.                 pIcode++;
  1248.                 ip++;
  1249.             }
  1250.             pIcode++;
  1251.             break;
  1252.  
  1253.         case iOR:           /* Idiom 10 */
  1254.             idiom10 (pIcode, pEnd);
  1255.             pIcode++;
  1256.             break;
  1257.  
  1258.         case iNEG:          /* Idiom 11 */
  1259.             if (idiom11 (pIcode, pEnd))
  1260.             {
  1261.                 lhs = idCondExpLong (&pProc->localId, DST, pIcode, HIGH_FIRST, 
  1262.                                      ip, USE_DEF, 1);
  1263.                 rhs = unaryCondExp (NEGATION, lhs);
  1264.                 newAsgnHlIcode (pIcode, lhs, rhs);
  1265.                 invalidateIcode (pIcode+1);
  1266.                 invalidateIcode (pIcode+2);
  1267.                 pIcode += 3;
  1268.                 ip += 2;
  1269.             }
  1270.             else if (idiom16 (pIcode, pEnd))
  1271.             {
  1272.                 lhs = idCondExpReg (pIcode->ic.ll.dst.regi, pIcode->ic.ll.flg,
  1273.                                     &pProc->localId);
  1274.                 rhs = copyCondExp (lhs);
  1275.                 rhs = unaryCondExp (NEGATION, lhs);
  1276.                 newAsgnHlIcode (pIcode, lhs, rhs);
  1277.                 invalidateIcode (pIcode+1);
  1278.                 invalidateIcode (pIcode+2);
  1279.                 pIcode += 3;
  1280.                 ip += 2;
  1281.             }
  1282.             else
  1283.                 pIcode++;
  1284.             break;
  1285.  
  1286.         case iNOP:
  1287.             invalidateIcode (pIcode++);
  1288.             break;
  1289.  
  1290.         case iENTER:        /* ENTER is equivalent to init PUSH bp */
  1291.             if (ip == 0)
  1292.                 pProc->flg |= (PROC_HLL | PROC_IS_HLL);
  1293.             pIcode++;
  1294.             break;
  1295.  
  1296.         case iXOR:          /* Idiom 7 */
  1297.             if (idiom21 (pIcode, pEnd))
  1298.             {
  1299.                 lhs = idCondExpLong (&pProc->localId, DST, pIcode,
  1300.                                      HIGH_FIRST, ip, E_DEF, 1);
  1301.                 rhs = idCondExpKte ((pIcode+1)->ic.ll.immed.op , 4);
  1302.                 newAsgnHlIcode (pIcode, lhs, rhs);
  1303.                 pIcode->du.use = 0;        /* clear register used in iXOR */
  1304.                 invalidateIcode (pIcode+1);
  1305.                 pIcode++;
  1306.                 ip++;
  1307.             }
  1308.             else if (idiom7 (pIcode))
  1309.             {
  1310.                 lhs = idCondExp (pIcode, DST, pProc, ip, pIcode, NONE);
  1311.                 rhs = idCondExpKte (0, 2);
  1312.                 newAsgnHlIcode (pIcode, lhs, rhs);
  1313.                 pIcode->du.use = 0;    /* clear register used in iXOR */
  1314.                 pIcode->ic.ll.flg |= I;
  1315.             } 
  1316.             pIcode++;
  1317.             break;
  1318.  
  1319.         default:
  1320.             pIcode++;
  1321.         }
  1322.         ip++;
  1323.     }
  1324.  
  1325.     /* Check if number of parameter bytes match their calling convention */
  1326.     if ((pProc->flg & PROC_HLL) && (pProc->args.csym)) 
  1327.     {
  1328.         pProc->args.minOff += (pProc->flg & PROC_FAR ? 4 : 2);
  1329.         delta = pProc->args.maxOff - pProc->args.minOff;
  1330.         if (pProc->cbParam != delta) 
  1331.         {
  1332.             pProc->cbParam = delta;
  1333.             pProc->flg |= (CALL_MASK & CALL_UNKNOWN);
  1334.         }
  1335.     } 
  1336. }
  1337.  
  1338.  
  1339. void bindIcodeOff (PPROC pProc)
  1340. /* Sets up the TARGET flag for jump target addresses, and
  1341.  * binds jump target addresses to icode offsets.    */
  1342. { Int i, j;                 /* idx into icode array */
  1343.   PICODE pIcode;            /* ptr icode array      */
  1344.   dword *p;                 /* for case table       */
  1345.  
  1346.     if (! pProc->Icode.GetNumIcodes())        /* No Icode */
  1347.         return;             
  1348.     pIcode = pProc->Icode.GetFirstIcode();
  1349.  
  1350.     /* Flag all jump targets for BB construction and disassembly stage 2 */
  1351.     for (i = 0; i < pProc->Icode.GetNumIcodes(); i++)
  1352.         if ((pIcode[i].ic.ll.flg & I) && JmpInst(pIcode[i].ic.ll.opcode))
  1353.         {
  1354.             if (pProc->Icode.labelSrch(pIcode[i].ic.ll.immed.op, &j))
  1355.             {
  1356.                 pIcode[j].ic.ll.flg |= TARGET;
  1357.             }
  1358.         }
  1359.  
  1360.     /* Finally bind jump targets to Icode offsets.  Jumps for which no label
  1361.      * is found (no code at dest. of jump) are simply left unlinked and 
  1362.      * flagged as going nowhere.  */
  1363.     pIcode = pProc->Icode.GetFirstIcode();
  1364.     for (i = 0; i < pProc->Icode.GetNumIcodes(); i++)
  1365.         if (JmpInst(pIcode[i].ic.ll.opcode))
  1366.         {
  1367.             if (pIcode[i].ic.ll.flg & I)
  1368.             {
  1369.                 if (! pProc->Icode.labelSrch(pIcode[i].ic.ll.immed.op, 
  1370.                                 (Int *)&pIcode[i].ic.ll.immed.op))
  1371.                     pIcode[i].ic.ll.flg |= NO_LABEL;
  1372.             }
  1373.             else if (pIcode[i].ic.ll.flg & SWITCH)
  1374.             {
  1375.                 p = pIcode[i].ic.ll.caseTbl.entries;
  1376.                 for (j = 0; j < pIcode[i].ic.ll.caseTbl.numEntries; j++, p++)
  1377.                     pProc->Icode.labelSrch(*p, (Int *)p);
  1378.             }
  1379.         }
  1380. }
  1381.  
  1382.  
  1383. void lowLevelAnalysis (PPROC pProc)
  1384. /* Performs idioms analysis, and propagates long operands, if any */
  1385. {
  1386.     /* Idiom analysis - sets up some flags and creates some HIGH_LEVEL
  1387.      * icodes */
  1388.     findIdioms (pProc); 
  1389.  
  1390.     /* Propagate HIGH_LEVEL idiom information for long operands */
  1391.     propLong (pProc);
  1392. }
  1393.