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

  1. /****************************************************************************
  2.  *$Log:    parser.c,v $
  3.  * Revision 2.24  94/03/14  08:45:39  cifuente
  4.  * flags changed to flags32.
  5.  * 
  6.  * Revision 2.23  94/02/22  15:17:35  cifuente
  7.  * Removed some unused code.
  8.  * 
  9.  * Revision 2.22  93/12/14  14:07:54  cifuente
  10.  * ic.ll.immed.proc has new level of indirection.
  11.  * 
  12.  * Revision 2.21  93/12/13  16:09:28  cifuente
  13.  * Fixed bug: synthetic icodes need LOW_LEVEL type.  Was causing
  14.  * problems in the du analysis.
  15.  * 
  16.  * Revision 2.20  93/12/13  12:25:11  cifuente
  17.  * strSize is now a global function.
  18.  * 
  19.  * Revision 2.18  93/11/18  11:33:15  emmerik
  20.  * Extra parameters to interactDis()
  21.  * 
  22.  * Revision 2.17  93/11/17  16:26:57  cifuente
  23.  * Call graph references
  24.  * 
  25.  * Revision 2.16  93/11/15  16:55:07  emmerik
  26.  * Minor change: call to disassembler with indirect jumps is now after the
  27.  * flags have been set
  28.  * 
  29.  * Revision 2.15  93/11/11  11:57:21  emmerik
  30.  * Keeps the name of the function from the .sig file (e.g. LXMUL@) even if it
  31.  * is not a real library function (i.e. does not exist in dcclibs.lst)
  32.  * 
  33.  * Revision 2.14  93/11/10  17:29:30  cifuente
  34.  * Procedure header, locals
  35.  * 
  36.  * Revision 2.13  93/10/29  13:32:28  cifuente
  37.  * IM_SRC use
  38.  * 
  39.  * Revision 2.12  93/10/25  10:58:41  cifuente
  40.  * New SYNTHETIC instructions for d/u analysis
  41.  * 
  42.  * Revision 2.11  93/10/20  14:40:44  cifuente
  43.  * New level of indirection for icode array (Icode.icode[])
  44.  * 
  45.  * Revision 2.10  93/10/11  11:39:22  cifuente
  46.  * Minor bugs checked (DST rather than SRC for use of PUSH and POP ops)
  47.  * 
  48.  * Revision 2.9  93/10/01  14:37:24  emmerik
  49.  * Uses prog.segMain to get the segment and offset of main corrent
  50.  * 
  51.  * Revision 2.8  93/10/01  09:00:05  cifuente
  52.  * boolT type - for compilation under unix SVR4.2
  53.  * 
  54.  * Revision 2.6  93/09/29  10:45:20  cifuente
  55.  * LOW_LEVEL and HIGH_LEVEL icode definitions.  Increases llIcode indirection
  56.  * by 2 levels.
  57.  * 
  58.  * Revision 2.4  93/09/17  08:34:31  cifuente
  59.  * Moved pProclist to a global
  60.  * 
  61.  * Revision 2.3  93/08/23  12:15:38  cifuente
  62.  * Interactive mode with curses
  63.  * 
  64.  * Revision 2.1  93/03/30  14:53:13  cifuente
  65.  * Compiled with gcc.
  66.  * 
  67.  *          RevComp project procedure list builder
  68.  ****************************************************************************/
  69.  
  70. #include "dcc.h"
  71. #include <string.h>
  72. #include <stdlib.h>        /* For exit() */
  73.  
  74. #ifdef __DOSWIN__
  75. #include <stdio.h>
  76. #endif
  77.  
  78. static void     FollowCtrl (PPROC pProc, PCALL_GRAPH pcallGraph, PSTATE pstate);
  79. static boolT    process_JMP (PICODE pIcode, PPROC pProc, PSTATE pstate,
  80.                              PCALL_GRAPH pcallGraph);
  81. static boolT    process_CALL(PICODE pIcode, PPROC pProc, PCALL_GRAPH pcallGraph,
  82.                              PSTATE pstate);
  83. static void     process_operands(PICODE pIcode, PPROC pProc, PSTATE pstate,
  84.                                  Int ix);
  85. static void     setBits(int16 type, dword start, dword len);
  86. static PSYM     updateGlobSym(dword operand, Int size, word duFlag);
  87. static void     process_MOV(PICODE pIcode, PSTATE pstate);
  88. static PSYM     lookupAddr (PMEM pm, PSTATE pstate, Int size, word duFlag);
  89.         void    interactDis(PPROC initProc, Int ic);
  90. static dword    SynthLab;
  91.  
  92.  
  93. void parse (PCALL_GRAPH *pcallGraph)
  94. /* Parses the program, builds the call graph, and returns the list of 
  95.  * procedures found     */
  96. { STATE state;
  97.  
  98.     /* Set initial state */
  99.     memset(&state, 0, sizeof(STATE));
  100.     setState(&state, rES, 0);   /* PSP segment */
  101.     setState(&state, rDS, 0);
  102.     setState(&state, rCS, prog.initCS);
  103.     setState(&state, rSS, prog.initSS);
  104.     setState(&state, rSP, prog.initSP);
  105.     state.IP = ((dword)prog.initCS << 4) + prog.initIP;
  106.     SynthLab = SYNTHESIZED_MIN;
  107.  
  108.  
  109.     /* Check for special settings of initial state, based on idioms of the
  110.         startup code */
  111.     checkStartup(&state);
  112.  
  113.     /* Make a struct for the initial procedure */
  114.     pProcList = allocStruc(PROCEDURE);
  115.     pProcList = (PPROC)memset(pProcList, 0, sizeof(PROCEDURE));
  116.     if (prog.offMain != -1)
  117.     {
  118.         /* We know where main() is. Start the flow of control from there */
  119.         pProcList->procEntry = prog.offMain;
  120.         /* In medium and large models, the segment of main may (will?) not be
  121.             the same as the initial CS segment (of the startup code) */
  122.         setState(&state, rCS, prog.segMain);
  123.         strcpy(pProcList->name, "main");
  124.         state.IP = prog.offMain;
  125.     }
  126.     else
  127.     {
  128.         /* Create initial procedure at program start address */
  129.         pProcList->procEntry = (dword)state.IP;
  130.     }
  131.     /* The state info is for the first procedure */
  132.     memcpy(&(pProcList->state), &state, sizeof(STATE));
  133.     pLastProc = pProcList;
  134.  
  135.     /* Set up call graph initial node */
  136.     *pcallGraph = allocStruc(CALL_GRAPH);
  137.     memset (*pcallGraph, 0, sizeof(CALL_GRAPH));
  138.     (*pcallGraph)->proc = pProcList;
  139.  
  140.     /* This proc needs to be called to set things up for LibCheck(), which
  141.         checks a proc to see if it is a know C (etc) library */
  142.     SetupLibCheck();
  143.  
  144.     /* Recursively build entire procedure list */
  145.     FollowCtrl (pProcList, *pcallGraph, &state);
  146.  
  147.     /* This proc needs to be called to clean things up from SetupLibCheck() */
  148.     CleanupLibCheck();
  149. }
  150.  
  151.  
  152. static void updateSymType (dword symbol, hlType symType, Int size)
  153. /* Updates the type of the symbol in the symbol table.  The size is updated
  154.  * if necessary (0 means no update necessary).      */
  155. { Int i;
  156.  
  157.     for (i = 0; i < symtab.csym; i++)
  158.       if (symtab.sym[i].label == symbol)  
  159.       {
  160.          symtab.sym[i].type = symType;
  161.          if (size != 0)
  162.             symtab.sym[i].size = size;
  163.          break;
  164.       }
  165. }
  166.  
  167.  
  168. Int strSize (byte *sym, char delim)
  169. /* Returns the size of the string pointed by sym and delimited by delim. 
  170.  * Size includes delimiter.     */
  171. { Int i;
  172.  
  173.     for (i = 0; *sym++ != delim; i++)  ;
  174.     return (i+1);
  175. }
  176.  
  177.  
  178. static void FollowCtrl (PPROC pProc, PCALL_GRAPH pcallGraph, PSTATE pstate) 
  179. /* FollowCtrl - Given an initial procedure, state information and symbol table
  180.  *      builds a list of procedures reachable from the initial procedure
  181.  *      using a depth first search.     */
  182. {
  183.     ICODE   Icode, *pIcode;     /* This gets copied to pProc->Icode[] later */
  184.     ICODE   eIcode;             /* extra icodes for iDIV, iIDIV, iXCHG */
  185.     PSYM    psym;
  186.     dword   offset;
  187.     Int     err;
  188.     boolT   done = FALSE;
  189.     Int     lab;
  190.  
  191.     if (strstr(pProc->name, "chkstk") != NULL)
  192.     {
  193.         // Danger! Dcc will likely fall over in this code.
  194.         // So we act as though we have done with this proc
  195. //        pProc->flg &= ~TERMINATES;            // Not sure about this
  196.         done = TRUE;
  197.         // And mark it as a library function, so structure() won't choke on it
  198.         pProc->flg |= PROC_ISLIB;
  199.         return;
  200.     }
  201.     if (option.VeryVerbose)
  202.     {
  203.         printf("Parsing proc %s at %lX\n", pProc->name, pstate->IP);
  204.     }
  205.  
  206.     while (! done && ! (err = scan(pstate->IP, &Icode)))
  207.     {
  208.         pstate->IP += (dword)Icode.ic.ll.numBytes;
  209.         setBits(BM_CODE, Icode.ic.ll.label, (dword)Icode.ic.ll.numBytes);
  210.  
  211.         process_operands(&Icode, pProc, pstate, pProc->Icode.GetNumIcodes());
  212.  
  213.         /* Keep track of interesting instruction flags in procedure */
  214.         pProc->flg |= (Icode.ic.ll.flg & (NOT_HLL | FLOAT_OP));
  215.  
  216.         /* Check if this instruction has already been parsed */
  217.         if (pProc->Icode.labelSrch(Icode.ic.ll.label, &lab))
  218.         {   /* Synthetic jump */
  219.             Icode.type = LOW_LEVEL;
  220.             Icode.ic.ll.opcode = iJMP;
  221.             Icode.ic.ll.flg = I | SYNTHETIC | NO_OPS;
  222.             Icode.ic.ll.immed.op = pProc->Icode.GetLlLabel(lab);
  223.             Icode.ic.ll.label = SynthLab++;
  224.         }
  225.  
  226.         /* Copy Icode to Proc */
  227.         if ((Icode.ic.ll.opcode == iDIV) || (Icode.ic.ll.opcode == iIDIV))
  228.         {
  229.             /* MOV rTMP, reg */
  230.             memset (&eIcode, 0, sizeof (ICODE));
  231.             eIcode.type = LOW_LEVEL;
  232.             eIcode.ic.ll.opcode = iMOV;
  233.             eIcode.ic.ll.dst.regi = rTMP;
  234.             if (Icode.ic.ll.flg & B)
  235.             {
  236.                 eIcode.ic.ll.flg |= B;
  237.                 eIcode.ic.ll.src.regi = rAX;
  238.                 setRegDU (&eIcode, rAX, E_USE);
  239.             }
  240.             else    /* implicit dx:ax */
  241.             {
  242.                 eIcode.ic.ll.flg |= IM_SRC;
  243.                 setRegDU (&eIcode, rAX, E_USE);
  244.                 setRegDU (&eIcode, rDX, E_USE);
  245.             }
  246.             setRegDU (&eIcode, rTMP, E_DEF); 
  247.             eIcode.ic.ll.flg |= SYNTHETIC;
  248.             /* eIcode.ic.ll.label = SynthLab++; */
  249.             eIcode.ic.ll.label = Icode.ic.ll.label;
  250.             pIcode = pProc->Icode.addIcode(&eIcode);
  251.  
  252.             /* iDIV, iIDIV */
  253.             pIcode = pProc->Icode.addIcode(&Icode);
  254.  
  255.             /* iMOD */
  256.             memset (&eIcode, 0, sizeof (ICODE));
  257.             eIcode.type = LOW_LEVEL;
  258.             eIcode.ic.ll.opcode = iMOD;
  259.             memcpy (&eIcode.ic.ll.src, &Icode.ic.ll.src, sizeof(ICODEMEM));
  260.             memcpy (&eIcode.du, &Icode.du, sizeof(DU_ICODE));
  261.             eIcode.ic.ll.flg = (Icode.ic.ll.flg | SYNTHETIC);
  262.             eIcode.ic.ll.label = SynthLab++;
  263.             pIcode = pProc->Icode.addIcode(&eIcode);
  264.         }
  265.         else if (Icode.ic.ll.opcode == iXCHG)
  266.         {
  267.             /* MOV rTMP, regDst */
  268.             memset (&eIcode, 0, sizeof (ICODE));
  269.             eIcode.type = LOW_LEVEL;
  270.             eIcode.ic.ll.opcode = iMOV;
  271.             eIcode.ic.ll.dst.regi = rTMP;
  272.             eIcode.ic.ll.src.regi = Icode.ic.ll.dst.regi;
  273.             setRegDU (&eIcode, rTMP, E_DEF); 
  274.             setRegDU (&eIcode, eIcode.ic.ll.src.regi, E_USE); 
  275.             eIcode.ic.ll.flg |= SYNTHETIC;
  276.             /* eIcode.ic.ll.label = SynthLab++; */
  277.             eIcode.ic.ll.label = Icode.ic.ll.label; 
  278.             pIcode = pProc->Icode.addIcode(&eIcode);
  279.  
  280.             /* MOV regDst, regSrc */
  281.             Icode.ic.ll.opcode = iMOV;
  282.             Icode.ic.ll.flg |= SYNTHETIC;
  283.             /* Icode.ic.ll.label = SynthLab++; */
  284.             pIcode = pProc->Icode.addIcode(&Icode);
  285.             Icode.ic.ll.opcode = iXCHG; /* for next case */
  286.  
  287.             /* MOV regSrc, rTMP */ 
  288.             memset (&eIcode, 0, sizeof (ICODE));
  289.             eIcode.type = LOW_LEVEL;
  290.             eIcode.ic.ll.opcode = iMOV;
  291.             eIcode.ic.ll.dst.regi = Icode.ic.ll.src.regi;
  292.             eIcode.ic.ll.src.regi = rTMP;
  293.             setRegDU (&eIcode, eIcode.ic.ll.dst.regi, E_DEF);
  294.             setRegDU (&eIcode, rTMP, E_USE);
  295.             eIcode.ic.ll.flg |= SYNTHETIC;
  296.             eIcode.ic.ll.label = SynthLab++;
  297.             pIcode = pProc->Icode.addIcode(&eIcode);
  298.         } 
  299.         else
  300.             pIcode = pProc->Icode.addIcode(&Icode);
  301.  
  302.         switch (Icode.ic.ll.opcode) {
  303.         /*** Conditional jumps ***/
  304.         case iLOOP: case iLOOPE:    case iLOOPNE:
  305.         case iJB:   case iJBE:      case iJAE:  case iJA:
  306.         case iJL:   case iJLE:      case iJGE:  case iJG:
  307.         case iJE:   case iJNE:      case iJS:   case iJNS:
  308.         case iJO:   case iJNO:      case iJP:   case iJNP:
  309.         case iJCXZ:
  310.         {   STATE   StCopy;
  311.             int        ip        = pProc->Icode.GetNumIcodes()-1;    /* Index of this jump */
  312.             PICODE  prev    = pProc->Icode.GetIcode(ip-1);        /* Previous icode */
  313.             boolT   fBranch = FALSE;
  314.  
  315.             pstate->JCond.regi = 0;
  316.  
  317.             /* This sets up range check for indexed JMPs hopefully
  318.              * Handles JA/JAE for fall through and JB/JBE on branch
  319.             */
  320.             if (ip > 0 && prev->ic.ll.opcode == iCMP && (prev->ic.ll.flg & I))
  321.             {
  322.                 pstate->JCond.immed = (int16)prev->ic.ll.immed.op;
  323.                 if (Icode.ic.ll.opcode == iJA || Icode.ic.ll.opcode == iJBE)
  324.                     pstate->JCond.immed++;
  325.                 if (Icode.ic.ll.opcode == iJAE || Icode.ic.ll.opcode == iJA)
  326.                     pstate->JCond.regi = prev->ic.ll.dst.regi;
  327.                 fBranch = (boolT)
  328.                        (Icode.ic.ll.opcode == iJB || Icode.ic.ll.opcode == iJBE);
  329.             }
  330.  
  331.             memcpy(&StCopy, pstate, sizeof(STATE));
  332.  
  333.             /* Straight line code */
  334.             FollowCtrl (pProc, pcallGraph, &StCopy);
  335.  
  336.             if (fBranch)                /* Do branching code */
  337.             {
  338.                 // Ugh - prev may have moved due to the recursion above
  339.                 prev = pProc->Icode.GetIcode(ip-1);
  340.                 pstate->JCond.regi = prev->ic.ll.dst.regi;
  341.             }
  342.             /* Next icode. Note: not the same as GetLastIcode() because of the call
  343.                 to FollowCtrl() */
  344.             pIcode = pProc->Icode.GetIcode(ip);
  345.         }        /* Fall through to do the jump path */
  346.  
  347.         /*** Jumps ***/
  348.         case iJMP:
  349.         case iJMPF: /* Returns TRUE if we've run into a loop */
  350.             done = process_JMP (pIcode, pProc, pstate, pcallGraph);
  351.             break;
  352.  
  353.         /*** Calls ***/
  354.         case iCALL:
  355.         case iCALLF:
  356.             done = process_CALL (pIcode, pProc, pcallGraph, pstate);
  357.             break;
  358.  
  359.         /*** Returns ***/
  360.         case iRET:
  361.         case iRETF:
  362.             pProc->flg |= (Icode.ic.ll.opcode == iRET)? PROC_NEAR:PROC_FAR;
  363.                                         /* Fall through */
  364.         case iIRET:
  365.             pProc->flg &= ~TERMINATES;
  366.             done = TRUE;
  367.             break;
  368.  
  369.         case iINT:
  370.             if (Icode.ic.ll.immed.op == 0x21 && pstate->f[rAH])
  371.             {
  372.                Int funcNum = pstate->r[rAH];
  373.                Int operand;
  374.                Int size;
  375.  
  376.                /* Save function number */
  377.                pProc->Icode.GetIcode(pProc->Icode.GetNumIcodes() - 1)->ic.ll.dst.off = 
  378.                                                                 (int16)funcNum;
  379.  
  380.                /* Program termination: int21h, fn 00h, 31h, 4Ch */
  381.                done  = (boolT)(funcNum == 0x00 || funcNum == 0x31 ||
  382.                         funcNum == 0x4C);
  383.  
  384.                /* String functions: int21h, fn 09h */
  385.                if (pstate->f[rDX])      /* offset goes into DX */
  386.                     if (funcNum == 0x09)
  387.                     {
  388.                         operand = ((dword)(word)pstate->r[rDS]<<4) +
  389.                             (dword)(word)pstate->r[rDX];
  390.                            size = prog.fCOM ?
  391.                             strSize (&prog.Image[operand], '$') :
  392.                             strSize (&prog.Image[operand + 0x100], '$');
  393.                            updateSymType (operand, TYPE_STR, size);
  394.                      }
  395.             }
  396.             else if ((Icode.ic.ll.immed.op == 0x2F) && (pstate->f[rAH]))
  397.             {
  398.                 pProc->Icode.GetIcode(pProc->Icode.GetNumIcodes() - 1)->ic.ll.dst.off =
  399.                     pstate->r[rAH];
  400.             }
  401.             else    /* Program termination: int20h, int27h */
  402.                 done = (boolT)(Icode.ic.ll.immed.op == 0x20 ||
  403.                                             Icode.ic.ll.immed.op == 0x27);
  404.             if (done)
  405.                 pIcode->ic.ll.flg |= TERMINATES;
  406.             break;
  407.  
  408.         case iMOV:
  409.             process_MOV(pIcode, pstate);
  410.             break;
  411.  
  412.         /* case iXCHG:
  413.             process_MOV (pIcode, pstate);
  414.  
  415.             break; **** HERE ***/
  416.  
  417.         case iSHL:
  418.             if (pstate->JCond.regi == Icode.ic.ll.dst.regi)
  419.                if ((Icode.ic.ll.flg & I) && Icode.ic.ll.immed.op == 1)
  420.                 pstate->JCond.immed *= 2;
  421.                else
  422.                 pstate->JCond.regi = 0;
  423.             break;
  424.  
  425.         case iLEA:
  426.             if (Icode.ic.ll.src.regi == 0)      /* direct mem offset */
  427.                setState (pstate, Icode.ic.ll.dst.regi, Icode.ic.ll.src.off);
  428.             break;
  429.  
  430.         case iLDS: case iLES:
  431.             if ((psym = lookupAddr(&Icode.ic.ll.src, pstate, 4, USE))
  432.                 /* && (Icode.ic.ll.flg & SEG_IMMED) */ ) {
  433.                offset = LH(&prog.Image[psym->label]);
  434.                setState(pstate, (Icode.ic.ll.opcode == iLDS)? rDS: rES,
  435.                         LH(&prog.Image[psym->label + 2]));
  436.                setState(pstate, Icode.ic.ll.dst.regi, (int16)offset);
  437.                psym->type = TYPE_PTR;
  438.             }
  439.             break;
  440.         }
  441.     }
  442.  
  443.     if (err) {
  444.         pProc->flg &= ~TERMINATES;
  445.  
  446.         if (err == INVALID_386OP || err == INVALID_OPCODE)
  447.         {
  448.            fatalError(err, prog.Image[Icode.ic.ll.label], Icode.ic.ll.label);
  449.            pProc->flg |= PROC_BADINST;
  450.         }
  451.         else if (err == IP_OUT_OF_RANGE)
  452.            fatalError (err, Icode.ic.ll.label);
  453.         else
  454.            reportError(err, Icode.ic.ll.label);
  455.     }
  456. }
  457.  
  458.  
  459. static boolT process_JMP (PICODE pIcode, PPROC pProc, PSTATE pstate, 
  460.                           PCALL_GRAPH pcallGraph)
  461. /* process_JMP - Handles JMPs, returns TRUE if we should end recursion  */
  462. {   static byte i2r[4] = {rSI, rDI, rBP, rBX};
  463.     ICODE       Icode;
  464.     dword       cs, offTable, endTable;
  465.     dword       i, k, seg, target;
  466.     Int         tmp;
  467.  
  468.     if (pIcode->ic.ll.flg & I)
  469.     {
  470.         if (pIcode->ic.ll.opcode == iJMPF)
  471.            setState(pstate, rCS, LH(prog.Image + pIcode->ic.ll.label + 3));
  472.         i = pstate->IP = pIcode->ic.ll.immed.op;
  473.         if ((long)i < 0)
  474.         {
  475.             exit(1);
  476.         }
  477.  
  478.         /* Return TRUE if jump target is already parsed */
  479.         return pProc->Icode.labelSrch(i, &tmp);
  480.     }
  481.  
  482.     /* We've got an indirect JMP - look for switch() stmt. idiom of the form
  483.      *   JMP  word ptr  word_offset[rBX | rSI | rDI]        */
  484.     seg = (pIcode->ic.ll.src.seg)? pIcode->ic.ll.src.seg: rDS;
  485.  
  486.     /* Ensure we have a word offset & valid seg */
  487.     if (pIcode->ic.ll.opcode == iJMP && (pIcode->ic.ll.flg & WORD_OFF) &&
  488.         pstate->f[seg] &&
  489.         (pIcode->ic.ll.src.regi == INDEXBASE + 4 ||
  490.          pIcode->ic.ll.src.regi == INDEXBASE + 5 || /* Idx reg. BX, SI, DI */
  491.          pIcode->ic.ll.src.regi == INDEXBASE + 7))
  492.     {
  493.  
  494.         offTable = ((dword)(word)pstate->r[seg] << 4) + pIcode->ic.ll.src.off;
  495.  
  496.         /* Firstly look for a leading range check of the form:-
  497.          *      CMP {BX | SI | DI}, immed
  498.          *      JA | JAE | JB | JBE
  499.          * This is stored in the current state as if we had just
  500.          * followed a JBE branch (i.e. [reg] lies between 0 - immed).
  501.         */
  502.         if (pstate->JCond.regi == i2r[pIcode->ic.ll.src.regi-(INDEXBASE+4)])
  503.             endTable = offTable + pstate->JCond.immed;
  504.         else
  505.             endTable = (dword)prog.cbImage;
  506.  
  507.         /* Search for first byte flagged after start of table */
  508.         for (i = offTable; i <= endTable; i++)
  509.             if (BITMAP(i, BM_CODE | BM_DATA))
  510.                 break;
  511.         endTable = i & ~1;      /* Max. possible table size */
  512.  
  513.         /* Now do some heuristic pruning.  Look for ptrs. into the table
  514.          * and for addresses that don't appear to point to valid code.
  515.         */
  516.         cs = (dword)(word)pstate->r[rCS] << 4;
  517.         for (i = offTable; i < endTable; i += 2)
  518.         {
  519.             target = cs + LH(&prog.Image[i]);
  520.             if (target < endTable && target >= offTable)
  521.                 endTable = target;
  522.             else if (target >= (dword)prog.cbImage)
  523.                 endTable = i;
  524.         }
  525.  
  526.         for (i = offTable; i < endTable; i += 2)
  527.         {
  528.             target = cs + LH(&prog.Image[i]);
  529.             /* Be wary of 00 00 as code - it's probably data */
  530.             if (! (prog.Image[target] || prog.Image[target+1]) ||
  531.                 scan(target, &Icode))
  532.                 endTable = i;
  533.         }
  534.  
  535.         /* Now for each entry in the table take a copy of the current
  536.          * state and recursively call FollowCtrl(). */
  537.         if (offTable < endTable)
  538.         {
  539.             STATE   StCopy;
  540.             Int     ip;
  541.             dword  *psw;
  542.             
  543.             setBits(BM_DATA, offTable, endTable - offTable);
  544.  
  545.             pIcode->ic.ll.flg |= SWITCH;
  546.             pIcode->ic.ll.caseTbl.numEntries = (endTable - offTable) / 2;
  547.             psw = (dword*)allocMem(pIcode->ic.ll.caseTbl.numEntries*sizeof(dword));
  548.             pIcode->ic.ll.caseTbl.entries = psw;
  549.  
  550.             for (i = offTable, k = 0; i < endTable; i += 2)
  551.             {
  552.                 memcpy(&StCopy, pstate, sizeof(STATE));
  553.                 StCopy.IP = cs + LH(&prog.Image[i]);
  554.                 ip = pProc->Icode.GetNumIcodes();
  555.  
  556.                 FollowCtrl (pProc, pcallGraph, &StCopy);
  557.  
  558.                 pProc->Icode.GetIcode(ip)->ic.ll.caseTbl.numEntries = k++;
  559.                 pProc->Icode.GetIcode(ip)->ic.ll.flg |= CASE;
  560.                 *psw++ = pProc->Icode.GetLlLabel(ip);
  561.             }
  562.             return TRUE;
  563.         }
  564.     }
  565.  
  566.     /* Can't do anything with this jump */
  567.  
  568.     pProc->flg |= PROC_IJMP;
  569.     pProc->flg &= ~TERMINATES;
  570.     interactDis(pProc, pProc->Icode.GetNumIcodes()-1);
  571.     return TRUE;
  572. }
  573.  
  574.  
  575. static boolT process_CALL (PICODE pIcode, PPROC pProc, PCALL_GRAPH pcallGraph,
  576.                            PSTATE pstate)
  577. /* Process procedure call. 
  578.  * Note: We assume that CALL's will return unless there is good evidence to 
  579.  *       the contrary - thus we return FALSE unless all paths in the called 
  580.  *       procedure end in DOS exits.  This is reasonable since C procedures 
  581.  *       will always include the epilogue after the call anyway and it's to 
  582.  *       be assumed that if an assembler program contains a CALL that the 
  583.  *       programmer expected it to come back - otherwise surely a JMP would 
  584.  *       have been used.  */
  585. { PPROC p, pPrev;
  586.   Int   ip = pProc->Icode.GetNumIcodes() - 1;
  587.   STATE localState;     /* Local copy of the machine state */
  588.   dword off;
  589.   boolT indirect;
  590.  
  591.     /* For Indirect Calls, find the function address */
  592.     indirect = FALSE;
  593.     if (! (pIcode->ic.ll.flg & I)) 
  594.     {
  595.         /* Not immediate, i.e. indirect call */
  596.  
  597.         if (pIcode->ic.ll.dst.regi && (!option.Calls))
  598.         {
  599.             /* We have not set the brave option to attempt to follow
  600.                 the execution path through register indirect calls.
  601.                 So we just exit this function, and ignore the call.
  602.                 We probably should not have parsed this deep, anyway.
  603.             */
  604.             return FALSE;
  605.         }
  606.  
  607.         /* Offset into program image is seg:off of read input */
  608.         /* Note: this assumes that the pointer itself is at
  609.             es:0 where es:0 is the start of the image. This is
  610.             usually wrong! Consider also CALL [BP+0E] in which the
  611.             segment for the pointer is in SS! - Mike */
  612.  
  613.         off = (dword)(word)pIcode->ic.ll.dst.off +
  614.             ((dword)(word)pIcode->ic.ll.dst.segValue << 4);
  615.  
  616.         /* Address of function is given by 4 (CALLF) or 2 (CALL) bytes at 
  617.          * previous offset into the program image */
  618.         if (pIcode->ic.ll.opcode == iCALLF)
  619.             pIcode->ic.ll.immed.op = LH(&prog.Image[off]) + 
  620.                 ((dword)(LH(&prog.Image[off+2])) << 4);
  621.         else
  622.             pIcode->ic.ll.immed.op = LH(&prog.Image[off]) + 
  623.                                     ((dword)(word)pProc->state.r[rCS] << 4); 
  624.         pIcode->ic.ll.flg |= I;
  625.         indirect = TRUE;
  626.     }
  627.  
  628.     /* Process CALL.  Function address is located in pIcode->ic.ll.immed.op */
  629.     if (pIcode->ic.ll.flg & I) 
  630.     {
  631.         /* Search procedure list for one with appropriate entry point */
  632.         for (p = pProcList; p && p->procEntry != pIcode->ic.ll.immed.op;
  633.              p = p->next)
  634.             pPrev = p;
  635.  
  636.         /* Create a new procedure node and save copy of the state */
  637.         if (! p) {
  638.             p = allocStruc(PROCEDURE);
  639.             p = (PPROC)memset(p, 0, sizeof(PROCEDURE));
  640.             pPrev->next = p;
  641.             p->prev = pPrev;
  642.             p->procEntry = pIcode->ic.ll.immed.op;
  643.             pLastProc = p;      /* Pointer to last node in the list */
  644.  
  645.             LibCheck(p);
  646.  
  647.             if (p->flg & PROC_ISLIB)
  648.             {
  649.                 /* A library function. No need to do any more to it */
  650.                 insertCallGraph (pcallGraph, pProc, p);
  651.                 pProc->Icode.GetIcode(ip)->ic.ll.immed.proc.proc = p;
  652.                 return FALSE;
  653.             }
  654.  
  655.             if (indirect)
  656.                 p->flg |= PROC_ICALL;
  657.  
  658.             if (p->name[0] == '\0')     /* Don't overwrite existing name */
  659.             {
  660.                 sprintf(p->name, "proc_%ld", ++prog.cProcs);
  661.             }
  662.             p->depth = pProc->depth + 1;
  663.             p->flg |= TERMINATES;
  664.  
  665.             /* Save machine state in localState, load up IP and CS.*/
  666.             memcpy (&localState, pstate, sizeof(STATE));
  667.             pstate->IP = pIcode->ic.ll.immed.op;
  668.             if (pIcode->ic.ll.opcode == iCALLF)
  669.                setState (pstate, rCS, LH(prog.Image + pIcode->ic.ll.label + 3));
  670.             memcpy(&(p->state), pstate, sizeof(STATE));
  671.  
  672.             /* Insert new procedure in call graph */
  673.             insertCallGraph (pcallGraph, pProc, p);
  674.  
  675.             /* Process new procedure */
  676.             FollowCtrl (p, pcallGraph, pstate);
  677.             
  678.             /* Restore segment registers & IP from localState */
  679.             pstate->IP = localState.IP;
  680.             setState (pstate, rCS, localState.r[rCS]);
  681.             setState (pstate, rDS, localState.r[rDS]);
  682.             setState (pstate, rES, localState.r[rES]);
  683.             setState (pstate, rSS, localState.r[rSS]);
  684.  
  685.         }
  686.         else
  687.             insertCallGraph (pcallGraph, pProc, p);
  688.  
  689.         pProc->Icode.GetIcode(ip)->ic.ll.immed.proc.proc = p;   /* ^ target proc */
  690.         /* return ((p->flg & TERMINATES) != 0); */
  691.         return FALSE;
  692.     }
  693.     return FALSE;                // Cristina, please check!!
  694. }
  695.  
  696.  
  697. static void process_MOV(PICODE pIcode, PSTATE pstate)
  698. /* process_MOV - Handles state changes due to simple assignments    */
  699. { PSYM  psym, psym2;        /* Pointer to symbol in global symbol table */
  700.   byte  dstReg = pIcode->ic.ll.dst.regi;
  701.   byte  srcReg = pIcode->ic.ll.src.regi;
  702.  
  703.     if (dstReg > 0 && dstReg < INDEXBASE)
  704.     {
  705.         if (pIcode->ic.ll.flg & I)
  706.             setState(pstate, dstReg, (int16)pIcode->ic.ll.immed.op);
  707.         else if (srcReg == 0)   /* direct memory offset */
  708.         {
  709.             psym = lookupAddr(&pIcode->ic.ll.src, pstate, 2, USE);
  710.             if (psym && ((psym->flg & SEG_IMMED) || (psym->duVal & VAL)))
  711.                setState(pstate, dstReg, LH(&prog.Image[psym->label]));
  712.         }
  713.         else if (srcReg < INDEXBASE && pstate->f[srcReg])  /* reg */
  714.         {
  715.             setState(pstate, dstReg, pstate->r[srcReg]);
  716.  
  717.             /* Follow moves of the possible index register */
  718.             if (pstate->JCond.regi == srcReg)
  719.                 pstate->JCond.regi = dstReg;
  720.         }
  721.     }
  722.     else if (dstReg == 0) {     /* direct memory offset */
  723.         psym = lookupAddr (&pIcode->ic.ll.dst, pstate, 2, DEF);
  724.         if (psym && ! (psym->duVal & VAL))      /* no initial value yet */
  725.            if (pIcode->ic.ll.flg & I)   {       /* immediate */
  726.             prog.Image[psym->label] = (byte)pIcode->ic.ll.immed.op;
  727.             prog.Image[psym->label+1] = (byte)(pIcode->ic.ll.immed.op>>8);
  728.             psym->duVal |= VAL;
  729.            }
  730.            else if (srcReg == 0) {      /* direct mem offset */
  731.             psym2 = lookupAddr (&pIcode->ic.ll.src, pstate, 2, USE);
  732.             if (psym2 && ((psym->flg & SEG_IMMED) || (psym->duVal & VAL)))
  733.             {
  734.                prog.Image[psym->label] = (byte)prog.Image[psym2->label];
  735.                prog.Image[psym->label+1] =
  736.                                 (byte)(prog.Image[psym2->label+1] >> 8);
  737.                psym->duVal |= VAL;
  738.             }
  739.            }
  740.            else if (srcReg < INDEXBASE && pstate->f[srcReg])  /* reg */
  741.            {
  742.             prog.Image[psym->label] = (byte)pstate->r[srcReg];
  743.             prog.Image[psym->label+1] = (byte)(pstate->r[srcReg] >> 8);
  744.             psym->duVal |= VAL;
  745.            }
  746.     }
  747. }
  748.  
  749.  
  750. /* Type of the symbol according to the number of bytes it uses */ 
  751. static hlType cbType[] = {TYPE_UNKNOWN, TYPE_BYTE_UNSIGN, TYPE_WORD_SIGN,
  752.                           TYPE_UNKNOWN, TYPE_LONG_SIGN};
  753.  
  754. static PSYM updateGlobSym (dword operand, Int size, word duFlag)
  755. /* Creates an entry in the global symbol table (symtab) if the variable
  756.  * is not there yet.  If it is part of the symtab, the size of the variable
  757.  * is checked and updated if the old size was less than the new size (ie.
  758.  * the maximum size is always saved).   */
  759. {   Int i;
  760.  
  761.     /* Check for symbol in symbol table */
  762.     for (i = 0; i < symtab.csym; i++)
  763.         if (symtab.sym[i].label == operand) {
  764.             if (symtab.sym[i].size < size)
  765.                 symtab.sym[i].size = size;
  766.             break;
  767.         }
  768.  
  769.     /* New symbol, not in symbol table */
  770.     if (i == symtab.csym) {
  771.         if (++symtab.csym > symtab.alloc) {
  772.             symtab.alloc += 5;
  773.             symtab.sym = (PSYM)reallocVar(symtab.sym, symtab.alloc * sizeof(SYM));
  774.             memset (&symtab.sym[i], 0, 5 * sizeof(SYM));
  775.         }
  776.         sprintf (symtab.sym[i].name, "var%05lX", operand);
  777.         symtab.sym[i].label = operand;
  778.         symtab.sym[i].size  = size;
  779.         symtab.sym[i].type = cbType[size];
  780.         if (duFlag == USE)  /* must already have init value */
  781.             symtab.sym[i].duVal = USEVAL;
  782.         else
  783.             symtab.sym[i].duVal = duFlag;
  784.     }
  785.     return (&symtab.sym[i]);
  786. }
  787.  
  788.  
  789. static void updateFrameOff (PSTKFRAME ps, int16 off, Int size, word duFlag)
  790. /* Updates the offset entry to the stack frame table (arguments),
  791.  * and returns a pointer to such entry. */
  792. { Int   i;
  793.  
  794.     /* Check for symbol in stack frame table */
  795.     for (i = 0; i < ps->csym; i++)
  796.     {
  797.         if (ps->sym[i].off == off)
  798.         {
  799.             if (ps->sym[i].size < size)
  800.             {
  801.                 ps->sym[i].size = size;
  802.             }
  803.             break;
  804.         }
  805.     }
  806.  
  807.     /* New symbol, not in table */
  808.     if (i == ps->csym)
  809.     {
  810.         if (++ps->csym > ps->alloc)
  811.         {
  812.             ps->alloc += 5;
  813.             ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM));
  814.             memset(&ps->sym[i], 0, 5*sizeof(STKSYM));
  815.         }
  816.         sprintf (ps->sym[i].name, "arg%ld", i); 
  817.         ps->sym[i].off = off;
  818.         ps->sym[i].size  = size;
  819.         ps->sym[i].type = cbType[size];
  820.         if (duFlag == USE)  /* must already have init value */
  821.             ps->sym[i].duVal = USEVAL;
  822.         else
  823.             ps->sym[i].duVal = duFlag;
  824.         ps->cb += size;
  825.         ps->numArgs++;
  826.     }
  827.  
  828.     /* Save maximum argument offset */
  829.     if ((dword)ps->maxOff < (off + (dword)size))
  830.         ps->maxOff = off + (int16)size;
  831. }
  832.  
  833.  
  834. static PSYM lookupAddr (PMEM pm, PSTATE pstate, Int size, word duFlag)
  835. /* lookupAddr - Looks up a data reference in the symbol table and stores it 
  836.  *      if necessary.  Returns a pointer to the symbol in the
  837.  *      symbol table, or Null if it's not a direct memory offset.  */
  838. {   Int     i;
  839.     PSYM    psym;
  840.     dword   operand;
  841.  
  842.     if (pm->regi == 0)  {       /* Global var */
  843.         if (pm->segValue) { /* there is a value in the seg field */
  844.             operand = opAdr (pm->segValue, pm->off);
  845.             psym = updateGlobSym (operand, size, duFlag);
  846.  
  847.             /* Check for out of bounds */
  848.             if (psym->label >= (dword)prog.cbImage)
  849.                return (NULL);
  850.             return (psym);
  851.         }
  852.         else if (pstate->f[pm->seg]) {      /* new value */
  853.             pm->segValue = pstate->r[pm->seg];
  854.             operand = opAdr(pm->segValue, pm->off);
  855.             i = symtab.csym;
  856.             psym = updateGlobSym (operand, size, duFlag);
  857.  
  858.             /* Flag new memory locations that are segment values */
  859.             if (symtab.csym > i) {
  860.                 if (size == 4)
  861.                     operand += 2;   /* High word */
  862.                 for (i = 0; i < prog.cReloc; i++)
  863.                     if (prog.relocTable[i] == operand) {
  864.                         psym->flg = SEG_IMMED;
  865.                         break;
  866.                     }
  867.             }
  868.             
  869.             /* Check for out of bounds */
  870.             if (psym->label >= (dword)prog.cbImage)
  871.                return (NULL);
  872.             return (psym);
  873.         }
  874.     }
  875.     return (NULL);
  876. }
  877.  
  878.  
  879. void setState(PSTATE pstate, word reg, int16 value)
  880. /* setState - Assigns a value to a reg.     */
  881. {
  882.     value &= 0xFFFF;
  883.     pstate->r[reg] = value;
  884.     pstate->f[reg] = TRUE;
  885.     switch (reg) {
  886.     case rAX: case rCX: case rDX: case rBX:
  887.         pstate->r[reg + rAL - rAX] = value & 0xFF;
  888.         pstate->f[reg + rAL - rAX] = TRUE;
  889.         pstate->r[reg + rAH - rAX] = (value >> 8) & 0xFF;
  890.         pstate->f[reg + rAH - rAX] = TRUE;
  891.         break;
  892.  
  893.     case rAL: case rCL: case rDL: case rBL:
  894.         if (pstate->f[reg - rAL + rAH]) {
  895.             pstate->r[reg - rAL + rAX] =
  896.                 (pstate->r[reg - rAL + rAH] << 8) + (value & 0xFF);
  897.             pstate->f[reg - rAL + rAX] = TRUE;
  898.         }
  899.         break;
  900.  
  901.     case rAH: case rCH: case rDH: case rBH:
  902.         if (pstate->f[reg - rAH + rAL]) {
  903.             pstate->r[reg - rAH + rAX] =
  904.                 pstate->r[reg - rAH + rAL] + ((value & 0xFF) << 8);
  905.             pstate->f[reg - rAH + rAX] = TRUE;
  906.         }
  907.         break;
  908.     }
  909. }
  910.  
  911.  
  912. boolT labelSrch(PICODE pIcode, Int numIp, dword target, Int *pIndex)
  913. /* labelSrchRepl - Searches Icode for instruction with label = target, and
  914.     replaces *pIndex with an icode index */
  915. {
  916.     Int  i;
  917.  
  918.     for (i = 0; i < numIp; i++)
  919.     {
  920.         if (pIcode[i].ic.ll.label == target)
  921.         {
  922.             *pIndex = i;
  923.             return TRUE;
  924.         }
  925.     }
  926.     return FALSE;
  927. }
  928.  
  929.  
  930. static void setBits(int16 type, dword start, dword len)
  931. /* setBits - Sets memory bitmap bits for BM_CODE or BM_DATA (additively) */
  932. {
  933.     dword   i;
  934.  
  935.     if (start < (dword)prog.cbImage)
  936.     {
  937.         if (start + len > (dword)prog.cbImage)
  938.             len = (dword)(prog.cbImage - start);
  939.  
  940.         for (i = start + len - 1; i >= start; i--)
  941.         {
  942.             prog.map[i >> 2] |= type << ((i & 3) << 1);
  943.             if (i == 0) break;        // Fixes inf loop!
  944.         }
  945.     }
  946. }
  947.  
  948.  
  949. /* DU bit definitions for each reg value - including index registers */
  950. dword duReg[] = { 0x00, 
  951.             0x11001, 0x22002, 0x44004, 0x88008, /* word regs    */
  952.             0x10, 0x20, 0x40, 0x80, 
  953.             0x100, 0x200, 0x400, 0x800,         /* seg regs     */
  954.             0x1000, 0x2000, 0x4000, 0x8000,     /* byte regs    */ 
  955.             0x10000, 0x20000, 0x40000, 0x80000, 
  956.             0x100000,                           /* tmp reg      */
  957.             0x48, 0x88, 0x60, 0xA0,             /* index regs   */
  958.             0x40, 0x80, 0x20, 0x08 };
  959.  
  960.  
  961. static void use (opLoc d, PICODE pIcode, PPROC pProc, PSTATE pstate, Int size,
  962.                  Int ix)
  963. /* Checks which registers where used and updates the du.u flag.  
  964.  * Places local variables on the local symbol table.    
  965.  * Arguments: d     : SRC or DST icode operand
  966.  *            pIcode: ptr to icode instruction
  967.  *            pProc : ptr to current procedure structure
  968.  *            pstate: ptr to current procedure state
  969.  *            size  : size of the operand
  970.  *            ix    : current index into icode array    */
  971. { PMEM  pm   = (d == SRC)? &pIcode->ic.ll.src: &pIcode->ic.ll.dst;
  972.   PSYM  psym;
  973.  
  974.     if (pm->regi == 0 || pm->regi >= INDEXBASE) 
  975.     {
  976.         if (pm->regi == INDEXBASE + 6)      /* indexed on bp */
  977.         {
  978.             if (pm->off >= 2)
  979.                 updateFrameOff (&pProc->args, pm->off, size, USE);
  980.             else if (pm->off < 0) 
  981.                 newByteWordStkId (&pProc->localId, TYPE_WORD_SIGN, pm->off, 0);
  982.         }
  983.  
  984.         else if (pm->regi == INDEXBASE + 2 || pm->regi == INDEXBASE + 3)
  985.             newByteWordStkId (&pProc->localId, TYPE_WORD_SIGN, pm->off,
  986.                               (byte)((pm->regi == INDEXBASE + 2) ? rSI : rDI));
  987.  
  988.         else if ((pm->regi >= INDEXBASE + 4) && (pm->regi <= INDEXBASE + 7))
  989.         {
  990.             if ((pm->seg == rDS) && (pm->regi == INDEXBASE + 7))    /* bx */
  991.             {
  992.                 if (pm->off > 0)    /* global indexed variable */
  993.                     newIntIdxId (&pProc->localId, pm->segValue, pm->off, rBX,
  994.                                  ix, TYPE_WORD_SIGN);
  995.             }
  996.             pIcode->du.use |= duReg[pm->regi];
  997.         }
  998.  
  999.         else if (psym = lookupAddr(pm, pstate, size, USE))
  1000.         {
  1001.             setBits (BM_DATA, psym->label, (dword)size);
  1002.             pIcode->ic.ll.flg |= SYM_USE;
  1003.             pIcode->ic.ll.caseTbl.numEntries = psym - symtab.sym;
  1004.         }
  1005.     }
  1006.  
  1007.     /* Use of register */
  1008.     else if ((d == DST) || ((d == SRC) && (pIcode->ic.ll.flg & I) != I))
  1009.         pIcode->du.use |= duReg[pm->regi];
  1010. }
  1011.  
  1012.  
  1013. static void def (opLoc d, PICODE pIcode, PPROC pProc, PSTATE pstate, Int size,
  1014.                  Int ix)
  1015. /* Checks which registers were defined (ie. got a new value) and updates the
  1016.  * du.d flag.
  1017.  * Places local variables in the local symbol table.    */
  1018. { PMEM  pm   = (d == SRC)? &pIcode->ic.ll.src: &pIcode->ic.ll.dst;
  1019.   PSYM  psym;
  1020.  
  1021.     if (pm->regi == 0 || pm->regi >= INDEXBASE) 
  1022.     {
  1023.         if (pm->regi == INDEXBASE + 6)      /* indexed on bp */
  1024.         {
  1025.             if (pm->off >= 2)
  1026.                 updateFrameOff (&pProc->args, pm->off, size, DEF);
  1027.             else if (pm->off < 0)
  1028.                 newByteWordStkId (&pProc->localId, TYPE_WORD_SIGN, pm->off, 0);
  1029.         }
  1030.  
  1031.         else if (pm->regi == INDEXBASE + 2 || pm->regi == INDEXBASE + 3)
  1032.         {
  1033.             newByteWordStkId (&pProc->localId, TYPE_WORD_SIGN, pm->off,
  1034.                               (byte)((pm->regi == INDEXBASE + 2) ? rSI : rDI));
  1035.         }
  1036.  
  1037.         else if ((pm->regi >= INDEXBASE + 4) && (pm->regi <= INDEXBASE + 7))
  1038.         {
  1039.             if ((pm->seg == rDS) && (pm->regi == INDEXBASE + 7))    /* bx */
  1040.             {
  1041.                 if (pm->off > 0)        /* global var */
  1042.                     newIntIdxId (&pProc->localId, pm->segValue, pm->off, rBX,
  1043.                                  ix, TYPE_WORD_SIGN);
  1044.             }
  1045.             pIcode->du.use |= duReg[pm->regi];
  1046.         }
  1047.  
  1048.         else if (psym = lookupAddr(pm, pstate, size, DEF))
  1049.         {
  1050.             setBits(BM_DATA, psym->label, (dword)size);
  1051.             pIcode->ic.ll.flg |= SYM_DEF;
  1052.             pIcode->ic.ll.caseTbl.numEntries = psym - symtab.sym;
  1053.         }
  1054.     }
  1055.  
  1056.     /* Definition of register */
  1057.     else if ((d == DST) || ((d == SRC) && (pIcode->ic.ll.flg & I) != I))
  1058.     {
  1059.         pIcode->du.def |= duReg[pm->regi];
  1060.         pIcode->du1.numRegsDef++; 
  1061.     }
  1062. }
  1063.  
  1064.  
  1065. static void use_def(opLoc d, PICODE pIcode, PPROC pProc, PSTATE pstate, Int cb,
  1066.                     Int ix)
  1067. /* use_def - operand is both use and def'd.
  1068.  * Note: the destination will always be a register, stack variable, or global
  1069.  *       variable.      */
  1070. {
  1071.     PMEM    pm = (d == SRC)? &pIcode->ic.ll.src: &pIcode->ic.ll.dst;
  1072.  
  1073.     use (d, pIcode, pProc, pstate, cb, ix);
  1074.  
  1075.     if (pm->regi < INDEXBASE)                   /* register */
  1076.     {
  1077.         pIcode->du.def |= duReg[pm->regi];
  1078.         pIcode->du1.numRegsDef++; 
  1079.     }
  1080. }
  1081.  
  1082.  
  1083. static void process_operands(PICODE pIcode, PPROC pProc, PSTATE pstate, Int ix)
  1084. /* Set DU vector, local variables and arguments, and DATA bits in the
  1085.  * bitmap       */
  1086. { Int   i;
  1087.   Int   sseg = (pIcode->ic.ll.src.seg)? pIcode->ic.ll.src.seg: rDS;
  1088.   Int   cb   = (pIcode->ic.ll.flg & B) ? 1: 2;
  1089.   flags32 Imm  = (pIcode->ic.ll.flg & I);
  1090.  
  1091.     switch (pIcode->ic.ll.opcode) {
  1092.         case iAND:  case iOR:   case iXOR:
  1093.         case iSAR:  case iSHL:  case iSHR:
  1094.         case iRCL:  case iRCR:  case iROL:  case iROR:
  1095.         case iADD:  case iADC:  case iSUB:  case iSBB:
  1096.             if (! Imm) {
  1097.                 use(SRC, pIcode, pProc, pstate, cb, ix);
  1098.             }
  1099.         case iINC:  case iDEC:  case iNEG:  case iNOT:
  1100.         case iAAA:  case iAAD:  case iAAM:  case iAAS:
  1101.         case iDAA:  case iDAS:
  1102.             use_def(DST, pIcode, pProc, pstate, cb, ix);
  1103.             break;
  1104.  
  1105.         case iXCHG:
  1106.             /* This instruction is replaced by 3 instructions, only need
  1107.              * to define the src operand and use the destination operand
  1108.              * in the mean time.    */
  1109.             use(SRC, pIcode, pProc, pstate, cb, ix);
  1110.             def(DST, pIcode, pProc, pstate, cb, ix);
  1111.             break;
  1112.  
  1113.         case iTEST: case iCMP:
  1114.             if (! Imm)
  1115.                 use(SRC, pIcode, pProc, pstate, cb, ix);
  1116.             use(DST, pIcode, pProc, pstate, cb, ix);
  1117.             break;
  1118.  
  1119.         case iDIV:  case iIDIV:
  1120.             use(SRC, pIcode, pProc, pstate, cb, ix);
  1121.             if (cb == 1) 
  1122.                 pIcode->du.use |= duReg[rTMP];
  1123.             break;
  1124.  
  1125.         case iMUL:  case iIMUL:
  1126.             use(SRC, pIcode, pProc, pstate, cb, ix);
  1127.             if (! Imm)
  1128.             {
  1129.                 use (DST, pIcode, pProc, pstate, cb, ix);
  1130.                 if (cb == 1)
  1131.                 {
  1132.                     pIcode->du.def |= duReg[rAX]; 
  1133.                     pIcode->du1.numRegsDef++; 
  1134.                 }
  1135.                 else
  1136.                 {
  1137.                     pIcode->du.def |= (duReg[rAX] | duReg[rDX]);
  1138.                     pIcode->du1.numRegsDef += 2; 
  1139.                 }
  1140.             }
  1141.             else
  1142.                 def (DST, pIcode, pProc, pstate, cb, ix);
  1143.             break;
  1144.  
  1145.         case iSIGNEX:
  1146.             cb = (pIcode->ic.ll.flg & SRC_B) ? 1 : 2;
  1147.             if (cb == 1)                    /* byte */
  1148.             {
  1149.                 pIcode->du.def |= duReg[rAX];
  1150.                 pIcode->du1.numRegsDef++; 
  1151.                 pIcode->du.use |= duReg[rAL];
  1152.             }
  1153.             else                            /* word */
  1154.             {
  1155.                 pIcode->du.def |= (duReg[rDX] | duReg[rAX]);
  1156.                 pIcode->du1.numRegsDef += 2; 
  1157.                 pIcode->du.use |= duReg[rAX];
  1158.             }
  1159.             break;
  1160.  
  1161.         case iCALLF:            /* Ignore def's on CS for now */
  1162.             cb = 4;
  1163.         case iCALL:  case iPUSH:  case iPOP:
  1164.             if (! Imm) {
  1165.                 if (pIcode->ic.ll.opcode == iPOP)
  1166.                     def(DST, pIcode, pProc, pstate, cb, ix);
  1167.                 else
  1168.                     use(DST, pIcode, pProc, pstate, cb, ix);
  1169.             }
  1170.             break;
  1171.  
  1172.         case iESC:  /* operands may be larger */
  1173.             use(DST, pIcode, pProc, pstate, cb, ix);
  1174.             break;
  1175.  
  1176.         case iLDS:  case iLES:
  1177.             pIcode->du.def |= duReg[(pIcode->ic.ll.opcode == iLDS) ?
  1178.                 rDS : rES];
  1179.             pIcode->du1.numRegsDef++; 
  1180.             cb = 4;
  1181.         case iMOV:
  1182.             use(SRC, pIcode, pProc, pstate, cb, ix);
  1183.             def(DST, pIcode, pProc, pstate, cb, ix);
  1184.             break;
  1185.  
  1186.         case iLEA:
  1187.             use(SRC, pIcode, pProc, pstate, 2, ix);
  1188.             def(DST, pIcode, pProc, pstate, 2, ix);
  1189.             break;
  1190.  
  1191.         case iBOUND:
  1192.             use(SRC, pIcode, pProc, pstate, 4, ix);
  1193.             use(DST, pIcode, pProc, pstate, cb, ix);
  1194.             break;
  1195.  
  1196.         case iJMPF:
  1197.             cb = 4;
  1198.         case iJMP:
  1199.             if (! Imm)
  1200.                 use(SRC, pIcode, pProc, pstate, cb, ix);
  1201.             break;
  1202.  
  1203.         case iLOOP:  case iLOOPE:  case iLOOPNE:
  1204.             pIcode->du.def |= duReg[rCX];
  1205.             pIcode->du1.numRegsDef++; 
  1206.         case iJCXZ:
  1207.             pIcode->du.use |= duReg[rCX];
  1208.             break;
  1209.  
  1210.         case iREPNE_CMPS: case iREPE_CMPS:  case iREP_MOVS:
  1211.             pIcode->du.def |= duReg[rCX];
  1212.             pIcode->du1.numRegsDef++; 
  1213.             pIcode->du.use |= duReg[rCX];
  1214.         case iCMPS:  case iMOVS:
  1215.             pIcode->du.def |= duReg[rSI] | duReg[rDI];
  1216.             pIcode->du1.numRegsDef += 2; 
  1217.             pIcode->du.use |= duReg[rSI] | duReg[rDI] | duReg[rES] |
  1218.                                    duReg[sseg];
  1219.             break;
  1220.             
  1221.         case iREPNE_SCAS: case iREPE_SCAS:  case iREP_STOS:  case iREP_INS:
  1222.             pIcode->du.def |= duReg[rCX];
  1223.             pIcode->du1.numRegsDef++; 
  1224.             pIcode->du.use |= duReg[rCX];
  1225.         case iSCAS:  case iSTOS:  case iINS:
  1226.             pIcode->du.def |= duReg[rDI];
  1227.             pIcode->du1.numRegsDef++; 
  1228.             if (pIcode->ic.ll.opcode == iREP_INS || pIcode->ic.ll.opcode== iINS)
  1229.             {
  1230.                 pIcode->du.use |= duReg[rDI] | duReg[rES] | duReg[rDX];
  1231.             }
  1232.             else
  1233.             {
  1234.                 pIcode->du.use |= duReg[rDI] | duReg[rES] |
  1235.                                        duReg[(cb == 2)? rAX: rAL];
  1236.             }
  1237.             break;
  1238.  
  1239.         case iREP_LODS:
  1240.             pIcode->du.def |= duReg[rCX];
  1241.             pIcode->du1.numRegsDef++; 
  1242.             pIcode->du.use |= duReg[rCX];
  1243.         case iLODS:
  1244.             pIcode->du.def |= duReg[rSI] | duReg[(cb==2)? rAX: rAL];
  1245.             pIcode->du1.numRegsDef += 2; 
  1246.             pIcode->du.use |= duReg[rSI] | duReg[sseg];
  1247.             break;
  1248.  
  1249.         case iREP_OUTS:
  1250.             pIcode->du.def |= duReg[rCX];
  1251.             pIcode->du1.numRegsDef++; 
  1252.             pIcode->du.use |= duReg[rCX];
  1253.         case iOUTS:
  1254.             pIcode->du.def |= duReg[rSI];
  1255.             pIcode->du1.numRegsDef++; 
  1256.             pIcode->du.use |= duReg[rSI] | duReg[rDX] | duReg[sseg];
  1257.             break;
  1258.  
  1259.         case iIN:  case iOUT:
  1260.             def(DST, pIcode, pProc, pstate, cb, ix);
  1261.             if (! Imm)
  1262.             {
  1263.                 pIcode->du.use |= duReg[rDX];
  1264.             }
  1265.             break;
  1266.     }
  1267.  
  1268.     for (i = rSP; i <= rBH; i++)        /* Kill all defined registers */
  1269.         if (pIcode->ic.ll.flagDU.d & (1 << i))
  1270.             pstate->f[i] = FALSE;
  1271. }
  1272.  
  1273.