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

  1. /*
  2.  *$Log:    fixwild.c,v $
  3.  * Revision 1.10  93/10/28  11:10:10  emmerik
  4.  * Addressing mode [reg+nnnn] is now wildcarded
  5.  * 
  6.  * Revision 1.9  93/10/26  13:40:11  cifuente
  7.  * op0F(byte pat[])
  8.  * 
  9.  * Revision 1.8  93/10/26  13:01:29  emmerik
  10.  * Completed the odd opcodes, like 0F XX and F7. Result: some library
  11.  * functions that were not recognised before are recognised now.
  12.  * 
  13.  * Revision 1.7  93/10/11  11:37:01  cifuente
  14.  * First walk of HIGH_LEVEL icodes.
  15.  * 
  16.  * Revision 1.6  93/10/01  14:36:21  emmerik
  17.  * Added $ log, and made independant of dcc.h
  18.  * 
  19.  *
  20.  */
  21.  
  22. /*  *   *   *   *   *   *   *   *   *   *   *  *\
  23. *                                               *
  24. *           Fix Wild Cards Code                 *
  25. *                                               *
  26. \*  *   *   *   *   *   *   *   *   *   *   *  */
  27.  
  28. #include <memory.h>
  29.  
  30. #ifndef PATLEN
  31. #define PATLEN          23
  32. #define WILD            0xF4
  33. #endif
  34.  
  35. #ifndef bool
  36. #define bool  unsigned char
  37. #define TRUE  1
  38. #define FALSE 0
  39. #define byte  unsigned char
  40. #endif
  41.  
  42. static int pc;                              /* Indexes into pat[] */
  43.  
  44. /* prototypes */
  45. static bool ModRM(byte pat[]);              /* Handle the mod/rm byte */
  46. static bool TwoWild(byte pat[]);            /* Make the next 2 bytes wild */
  47. static bool FourWild(byte pat[]);           /* Make the next 4 bytes wild */
  48.        void fixWildCards(byte pat[]);       /* Main routine */
  49.  
  50.  
  51. /* Handle the mod/rm case. Returns true if pattern exhausted */
  52. static bool
  53. ModRM(byte pat[])
  54. {
  55.     byte op;
  56.  
  57.     /* A standard mod/rm byte follows opcode */
  58.     op = pat[pc++];                         /* The mod/rm byte */
  59.     if (pc >= PATLEN) return TRUE;          /* Skip Mod/RM */
  60.     switch (op & 0xC0)
  61.     {
  62.         case 0x00:                          /* [reg] or [nnnn] */
  63.             if ((op & 0xC7) == 6)
  64.             {
  65.                 /* Uses [nnnn] address mode */
  66.                 pat[pc++] = WILD;
  67.                 if (pc >= PATLEN) return TRUE;
  68.                 pat[pc++] = WILD;
  69.                 if (pc >= PATLEN) return TRUE;
  70.             }
  71.             break;
  72.         case 0x40:                          /* [reg + nn] */
  73.             if ((pc+=1) >= PATLEN) return TRUE;
  74.             break;
  75.         case 0x80:                          /* [reg + nnnn] */
  76.             /* Possibly just a long constant offset from a register,
  77.                 but often will be an index from a variable */
  78.             pat[pc++] = WILD;
  79.             if (pc >= PATLEN) return TRUE;
  80.             pat[pc++] = WILD;
  81.             if (pc >= PATLEN) return TRUE;
  82.             break;
  83.         case 0xC0:                          /* reg */
  84.             break;
  85.     }
  86.     return FALSE;
  87. }
  88.  
  89. /* Change the next two bytes to wild cards */
  90. static bool
  91. TwoWild(byte pat[])
  92. {
  93.     pat[pc++] = WILD;
  94.     if (pc >= PATLEN) return TRUE;      /* Pattern exhausted */
  95.     pat[pc++] = WILD;
  96.     if (pc >= PATLEN) return TRUE;
  97.     return FALSE;
  98. }
  99.  
  100. /* Change the next four bytes to wild cards */
  101. static bool
  102. FourWild(byte pat[])
  103. {
  104.             TwoWild(pat);
  105.     return  TwoWild(pat);
  106. }
  107.  
  108. /* Chop from the current point by wiping with zeroes. Can't rely on anything
  109.     after this point */
  110. static void
  111. chop(byte pat[])
  112. {
  113.     if (pc >= PATLEN) return;               /* Could go negative otherwise */
  114.     memset(&pat[pc], 0, PATLEN - pc);
  115. }
  116.  
  117. static bool
  118. op0F(byte pat[])
  119. {
  120.     /* The two byte opcodes */
  121.     byte op = pat[pc++];
  122.     switch (op & 0xF0)
  123.     {
  124.         case 0x00:              /* 00 - 0F */
  125.             if (op >= 0x06)     /* Clts, Invd, Wbinvd */
  126.                 return FALSE;
  127.             else
  128.             {
  129.                 /* Grp 6, Grp 7, LAR, LSL */
  130.                 return ModRM(pat);
  131.             }
  132.         case 0x20:              /* Various funnies, all with Mod/RM */
  133.             return ModRM(pat);
  134.  
  135.         case 0x80:
  136.             pc += 2;            /* Word displacement cond jumps */
  137.             return FALSE;
  138.  
  139.         case 0x90:              /* Byte set on condition */
  140.             return ModRM(pat);
  141.  
  142.         case 0xA0:
  143.             switch (op)
  144.             {
  145.                 case 0xA0:      /* Push FS */
  146.                 case 0xA1:      /* Pop  FS */
  147.                 case 0xA8:      /* Push GS */
  148.                 case 0xA9:      /* Pop  GS */
  149.                     return FALSE;
  150.  
  151.                 case 0xA3:      /* Bt  Ev,Gv */
  152.                 case 0xAB:      /* Bts Ev,Gv */
  153.                     return ModRM(pat);
  154.  
  155.                 case 0xA4:      /* Shld EvGbIb */
  156.                 case 0xAC:      /* Shrd EvGbIb */
  157.                     if (ModRM(pat)) return TRUE;
  158.                     pc++;       /* The #num bits to shift */
  159.                     return FALSE;
  160.  
  161.                 case 0xA5:      /* Shld EvGb CL */
  162.                 case 0xAD:      /* Shrd EvGb CL */
  163.                     return ModRM(pat);
  164.  
  165.                 default:        /* CmpXchg, Imul */
  166.                     return ModRM(pat);
  167.             }
  168.  
  169.         case 0xB0:
  170.             if (op == 0xBA)
  171.             {
  172.                 /* Grp 8: bt/bts/btr/btc Ev,#nn */
  173.                 if (ModRM(pat)) return TRUE;
  174.                 pc++;           /* The #num bits to shift */
  175.                 return FALSE;
  176.             }
  177.             return ModRM(pat);
  178.  
  179.         case 0xC0:
  180.             if (op <= 0xC1)
  181.             {
  182.                 /* Xadd */
  183.                 return ModRM(pat);
  184.             }
  185.             /* Else BSWAP */
  186.             return FALSE;
  187.  
  188.         default:
  189.             return FALSE;       /* Treat as double byte opcodes */
  190.  
  191.     }
  192.  
  193. }
  194.  
  195. /* Scan through the instructions in pat[], looking for opcodes that may
  196.     have operands that vary with different instances. For example, load and
  197.     store from statics, calls to other procs (even relative calls; they may
  198.     call procs loaded in a different order, etc).
  199.     Note that this procedure is architecture specific, and assumes the
  200.     processor is in 16 bit address mode (real mode).
  201.     PATLEN bytes are scanned.
  202. */
  203. void
  204. fixWildCards(byte pat[])
  205. {
  206.  
  207.     byte op, quad, intArg;
  208.  
  209.  
  210.     pc=0;
  211.     while (pc < PATLEN)
  212.     {
  213.         op = pat[pc++];
  214.         if (pc >= PATLEN) return;
  215.  
  216.         quad = (byte) (op & 0xC0);            /* Quadrant of the opcode map */
  217.         if (quad == 0)
  218.         {
  219.             /* Arithmetic group 00-3F */
  220.  
  221.             if ((op & 0xE7) == 0x26)        /* First check for the odds */
  222.             {
  223.                 /* Segment prefix: treat as 1 byte opcode */
  224.                 continue;
  225.             }
  226.             if (op == 0x0F)                 /* 386 2 byte opcodes */
  227.             {
  228.                 if (op0F(pat)) return;
  229.                 continue;
  230.             }
  231.  
  232.             if (op & 0x04)
  233.             {
  234.                 /* All these are constant. Work out the instr length */
  235.                 if (op & 2)
  236.                 {
  237.                     /* Push, pop, other 1 byte opcodes */
  238.                     continue;
  239.                 }
  240.                 else
  241.                 {
  242.                     if (op & 1)
  243.                     {
  244.                         /* Word immediate operands */
  245.                         pc += 2;
  246.                         continue;
  247.                     }
  248.                     else
  249.                     {
  250.                         /* Byte immediate operands */
  251.                         pc++;
  252.                         continue;
  253.                     }
  254.                 }
  255.             }
  256.             else
  257.             {
  258.                 /* All these have mod/rm bytes */
  259.                 if (ModRM(pat)) return;
  260.                 continue;
  261.             }
  262.         }
  263.         else if (quad == 0x40)
  264.         {
  265.             if ((op & 0x60) == 0x40)
  266.             {
  267.                 /* 0x40 - 0x5F -- these are inc, dec, push, pop of general
  268.                     registers */
  269.                 continue;
  270.             }
  271.             else
  272.             {
  273.                 /* 0x60 - 0x70 */
  274.                 if (op & 0x10)
  275.                 {
  276.                     /* 70-7F 2 byte jump opcodes */
  277.                     pc++;
  278.                     continue;
  279.                 }
  280.                 else
  281.                 {
  282.                     /* Odds and sods */
  283.                     switch (op)
  284.                     {
  285.                         case 0x60:  /* pusha */
  286.                         case 0x61:  /* popa */
  287.                         case 0x64:  /* overrides */
  288.                         case 0x65:
  289.                         case 0x66:
  290.                         case 0x67:
  291.                         case 0x6C:  /* insb DX */
  292.                         case 0x6E:  /* outsb DX */
  293.                             continue;
  294.  
  295.                         case 0x62:  /* bound */
  296.                             pc += 4;
  297.                             continue;
  298.  
  299.                         case 0x63:  /* arpl */
  300.                             if (TwoWild(pat)) return;
  301.                             continue;
  302.  
  303.                         case 0x68:  /* Push byte */
  304.                         case 0x6A:  /* Push byte */
  305.                         case 0x6D:  /* insb port */
  306.                         case 0x6F:  /* outsb port */
  307.                             /* 2 byte instr, no wilds */
  308.                             pc++;
  309.                             continue;
  310.  
  311.                     }
  312.                 }
  313.  
  314.             }
  315.         }
  316.         else if (quad == 0x80)
  317.         {
  318.             switch (op & 0xF0)
  319.             {
  320.                 case 0x80:          /* 80 - 8F */
  321.                     /* All have a mod/rm byte */
  322.                     if (ModRM(pat)) return;
  323.                     /* These also have immediate values */
  324.                     switch (op)
  325.                     {
  326.                         case 0x80:
  327.                         case 0x83:
  328.                             /* One byte immediate */
  329.                             pc++;
  330.                             continue;
  331.  
  332.                         case 0x81:
  333.                             /* Immediate 16 bit values might be constant, but
  334.                                 also might be relocatable. Have to make them
  335.                                 wild */
  336.                             if (TwoWild(pat)) return;
  337.                             continue;
  338.                     }
  339.                     continue;
  340.                 case 0x90:          /* 90 - 9F */
  341.                     if (op == 0x9A)
  342.                     {
  343.                         /* far call */
  344.                         if (FourWild(pat)) return;
  345.                         continue;
  346.                     }
  347.                     /* All others are 1 byte opcodes */
  348.                     continue;
  349.                 case 0xA0:          /* A0 - AF */
  350.                     if ((op & 0x0C) == 0)
  351.                     {
  352.                         /* mov al/ax to/from [nnnn] */
  353.                         if (TwoWild(pat)) return;
  354.                         continue;
  355.                     }
  356.                     else if ((op & 0xFE) == 0xA8)
  357.                     {
  358.                         /* test al,#byte or test ax,#word */
  359.                         if (op & 1) pc += 2;
  360.                         else        pc += 1;
  361.                         continue;
  362.                         
  363.                     }
  364.                 case 0xB0:          /* B0 - BF */
  365.                 {
  366.                     if (op & 8)
  367.                     {
  368.                         /* mov reg, #16 */
  369.                         /* Immediate 16 bit values might be constant, but also
  370.                             might be relocatable. For now, make them wild */
  371.                         if (TwoWild(pat)) return;
  372.                     }
  373.                     else
  374.                     {
  375.                         /* mov reg, #8 */
  376.                         pc++;
  377.                     }
  378.                     continue;
  379.                 }
  380.             }
  381.         }
  382.         else
  383.         {
  384.             /* In the last quadrant of the op code table */
  385.             switch (op)
  386.             {
  387.                 case 0xC0:          /* 386: Rotate group 2 ModRM, byte, #byte */
  388.                 case 0xC1:          /* 386: Rotate group 2 ModRM, word, #byte */
  389.                     if (ModRM(pat)) return;
  390.                     /* Byte immediate value follows ModRM */
  391.                     pc++;
  392.                     continue;
  393.  
  394.                 case 0xC3:          /* Return */
  395.                 case 0xCB:          /* Return far */
  396.                     chop(pat);
  397.                     return;
  398.                 case 0xC2:          /* Ret nnnn */
  399.                 case 0xCA:          /* Retf nnnn */
  400.                     pc += 2;
  401.                     chop(pat);
  402.                     return;
  403.  
  404.                 case 0xC4:          /* les Gv, Mp */
  405.                 case 0xC5:          /* lds Gv, Mp */
  406.                     if (ModRM(pat)) return;
  407.                     continue;
  408.  
  409.                 case 0xC6:          /* Mov ModRM, #nn */
  410.                     if (ModRM(pat)) return;
  411.                     /* Byte immediate value follows ModRM */
  412.                     pc++;
  413.                     continue;
  414.                 case 0xC7:          /* Mov ModRM, #nnnn */
  415.                     if (ModRM(pat)) return;
  416.                     /* Word immediate value follows ModRM */
  417.                     /* Immediate 16 bit values might be constant, but also
  418.                         might be relocatable. For now, make them wild */
  419.                     if (TwoWild(pat)) return;
  420.                     continue;
  421.  
  422.                 case 0xC8:          /* Enter Iw, Ib */
  423.                     pc += 3;        /* Constant word, byte */
  424.                     continue;
  425.                 case 0xC9:          /* Leave */
  426.                     continue;
  427.  
  428.                 case 0xCC:          /* Int 3 */
  429.                     continue;
  430.  
  431.                 case 0xCD:          /* Int nn */
  432.                     intArg = pat[pc++];
  433.                     if ((intArg >= 0x34) && (intArg <= 0x3B))
  434.                     {
  435.                         /* Borland/Microsoft FP emulations */
  436.                         if (ModRM(pat)) return;
  437.                     }
  438.                     continue;
  439.  
  440.                 case 0xCE:          /* Into */
  441.                     continue;
  442.  
  443.                 case 0xCF:          /* Iret */
  444.                     continue;
  445.  
  446.                 case 0xD0:          /* Group 2 rotate, byte, 1 bit */
  447.                 case 0xD1:          /* Group 2 rotate, word, 1 bit */
  448.                 case 0xD2:          /* Group 2 rotate, byte, CL bits */
  449.                 case 0xD3:          /* Group 2 rotate, word, CL bits */
  450.                     if (ModRM(pat)) return;
  451.                     continue;
  452.  
  453.                 case 0xD4:          /* Aam */
  454.                 case 0xD5:          /* Aad */
  455.                 case 0xD7:          /* Xlat */
  456.                     continue;
  457.  
  458.                 case 0xD8:
  459.                 case 0xD9:
  460.                 case 0xDA:
  461.                 case 0xDB:          /* Esc opcodes */
  462.                 case 0xDC:          /* i.e. floating point */
  463.                 case 0xDD:          /* coprocessor calls */
  464.                 case 0xDE:
  465.                 case 0xDF:
  466.                     if (ModRM(pat)) return;
  467.                     continue;
  468.  
  469.                 case 0xE0:          /* Loopne */
  470.                 case 0xE1:          /* Loope */
  471.                 case 0xE2:          /* Loop */
  472.                 case 0xE3:          /* Jcxz */
  473.                     pc++;           /* Short jump offset */
  474.                     continue;
  475.  
  476.                 case 0xE4:          /* in  al,nn */
  477.                 case 0xE6:          /* out nn,al */
  478.                     pc++;
  479.                     continue;
  480.  
  481.                 case 0xE5:          /* in ax,nn */
  482.                 case 0xE7:          /* in nn,ax */
  483.                     pc += 2;
  484.                     continue;
  485.  
  486.                 case 0xE8:          /* Call rel */
  487.                     if (TwoWild(pat)) return;
  488.                     continue;
  489.                 case 0xE9:          /* Jump rel, unconditional */
  490.                     if (TwoWild(pat)) return;
  491.                     chop(pat);
  492.                     return;
  493.                 case 0xEA:          /* Jump abs */
  494.                     if (FourWild(pat)) return;
  495.                     chop(pat);
  496.                     return;
  497.                 case 0xEB:          /* Jmp short unconditional */
  498.                     pc++;
  499.                     chop(pat);
  500.                     return;
  501.  
  502.                 case 0xEC:          /* In  al,dx */
  503.                 case 0xED:          /* In  ax,dx */
  504.                 case 0xEE:          /* Out dx,al */
  505.                 case 0xEF:          /* Out dx,ax */
  506.                     continue;
  507.  
  508.                 case 0xF0:          /* Lock */
  509.                 case 0xF2:          /* Repne */
  510.                 case 0xF3:          /* Rep/repe */
  511.                 case 0xF4:          /* Halt */
  512.                 case 0xF5:          /* Cmc */
  513.                 case 0xF8:          /* Clc */
  514.                 case 0xF9:          /* Stc */
  515.                 case 0xFA:          /* Cli */
  516.                 case 0xFB:          /* Sti */
  517.                 case 0xFC:          /* Cld */
  518.                 case 0xFD:          /* Std */
  519.                     continue;
  520.  
  521.                 case 0xF6:          /* Group 3 byte test/not/mul/div */
  522.                 case 0xF7:          /* Group 3 word test/not/mul/div */
  523.                 case 0xFE:          /* Inc/Dec group 4 */
  524.                     if (ModRM(pat)) return;
  525.                     continue;
  526.  
  527.                 case 0xFF:          /* Group 5 Inc/Dec/Call/Jmp/Push */
  528.                     /* Most are like standard ModRM */
  529.                     if (ModRM(pat)) return;
  530.                     continue;
  531.  
  532.                 default:            /* Rest are single byte opcodes */
  533.                     continue;
  534.             }
  535.         }
  536.     }
  537. }
  538.  
  539.