home *** CD-ROM | disk | FTP | other *** search
/ Total Destruction / Total_Destruction.iso / addons / Lccwin32.exe / Lccwin32 / lccpub / src / Optim.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-11  |  93.0 KB  |  3,505 lines

  1. /*
  2.     A peephole optimizer for lcc
  3.     ----------------------------
  4.  
  5. Section 1:
  6. ---------
  7. Overall design.
  8. The optimizer receives its input from the compiler as an ascii instruction
  9. stream. When the function 'genasm' sees a label, it will send the contents of
  10. the buffer to the optimizer with a call to the function 'SendToOptimizer'.
  11. The entry point in this file is the function 'ChangeBlock', that performs the
  12. following actions:
  13.     1. Parses the instructions, setting flags for certain characteristics,
  14.        setting register numbers, etc.
  15.     2. Calls the 'Optimize block' function the scan the block for instruction
  16.        to be changed/deleted.
  17.  
  18. The strategy of this peephole optimizer is to build a machine state, and
  19. try to keep it coherent with the operations performed in a block. It will
  20. try to eliminate redundant loads of registers, replace certains registers
  21. with other free ones, replace certain sequences of instruction lcc generates
  22. with other more efficient ones, etc. It is certainly limited to lcc, since
  23. many of the (implicit) assumptions about the code would preclude its use
  24. as a more general peephole optimizer.
  25.  
  26. */
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #define ANALYZER
  31. #ifdef STANDALONE
  32. #define DEBUGOPTIM
  33. #include <time.h>
  34. int vmask[] = { 1, 0 };
  35. #endif
  36. extern int genlabel(int);
  37. #include <assert.h>
  38. #define MAXIDSIZE 50
  39. /*
  40. The 'Instruction' data structure. This is built now by the parser of
  41. instructions, but it would naturally much more efficient to have the
  42. characteristics of those instructions built in to the tables of the
  43. compiler
  44. */
  45. typedef struct tagInstruction {
  46.     unsigned char Name[10]; /* opcode */
  47.     unsigned char src[MAXIDSIZE];  /* source of the data */
  48.     unsigned char dst[MAXIDSIZE];  /* destination of the data */
  49.     unsigned char *Start;   /* Pointer to the beginning of the instruction */
  50.                 /* in the assembler buffer */
  51.     unsigned char *End;    /* pointer to the end of the instruction */
  52.     long Flags;
  53.     unsigned short ChangedIdx; /* Index of the replace instruction in the */
  54.                 /* instruction table */
  55.     unsigned short SrcReg;  /* Source register number */
  56.     unsigned short DstReg;  /* destination reg number */
  57. }Instruction;
  58. /* instruction Flags field */
  59. #define DELETED            0x1
  60. #define CHANGED            0x2
  61. #define ISCALL            0x4
  62. #define CLOBBERS        0x8
  63. #define ISLOCAL            0x10
  64. #define ISARGUMENT        0x20
  65. #define SRCDEREFERENCE    0x40
  66. #define DSTDEREFERENCE    0x80
  67. #define SRCOFFSET        0x100
  68. #define DSTOFFSET        0x200
  69. #define ISJUMP            0x400
  70. #define ISFLOAT            0x800
  71. #define TRUNCATED        0x1000
  72. #define ISMOVL            0x2000
  73. #define ISMOVSB            0x4000
  74. #define    ISGENERICMOVE    0x8000
  75. #define ISMOVSWL        0x10000
  76. #define ISMOVSBL        0x20000
  77. #define ISLEAL            0x40000
  78. #define ISCOMPARE        0x80000
  79. #define ISREGSRC        0x100000
  80. #define ISREGDST        0x200000
  81. #define ADDED            0x400000
  82. #define STACKADJUST        0x800000
  83.  
  84. /*
  85. The instruction table contains two parts:
  86. 1. The instructions that belong to the block being analyzed now.
  87. 2. The changed instructions.
  88.  
  89. Each changed instruction contains the index of the position of the changed
  90. instruction contents in its ChangedIndex field, set by the function
  91. 'GetNextChangedInstruction'
  92. */
  93. /* Number of instructions in the instruction table */
  94. #define MAXINSTRUCTION 600
  95. /* Register numbers */
  96. #define EAX        1
  97. #define EBX        2
  98. #define ECX        3
  99. #define    EDX        4
  100. #define ESI        5
  101. #define EDI        6
  102. #define EBP        7
  103. #define    ESP        8
  104. #define    AX        9
  105. #define    BX        10
  106. #define CX        11
  107. #define DX        12
  108. #define SI        13
  109. #define DI        14
  110. #define BP        15
  111. #define SP        16
  112. #define MM0        17
  113. #define MM1        18
  114. #define    MM2        19
  115. #define MM3        20
  116. #define    MM4        21
  117. #define    MM5        22
  118. #define    MM6        23
  119. #define    MM7        24
  120.  
  121. static unsigned char *RegisterNames[] = {
  122.     "NULL",
  123.     "eax",
  124.     "ebx",
  125.     "ecx",
  126.     "edx",
  127.     "esi",
  128.     "edi",
  129.     "ebp",
  130.     "esp"
  131.     "mm0",
  132.     "mm1",
  133.     "mm2",
  134.     "mm3",
  135.     "mm4",
  136.     "mm5",
  137.     "mm6",
  138.     "mm7"
  139. };
  140. int ediIsSaved=1,esiIsSaved=1;
  141. static Instruction InstructionTable[MAXINSTRUCTION];
  142. static int InstructionIndex = 0;
  143. static int recursion = 0;
  144.  
  145. typedef struct tagbasicBlock {
  146.     char Label[25];
  147.     int calls;
  148.     int NrOfInstructions;
  149.     char Registers[SP+1];
  150.     int Flags;
  151.     unsigned short FirstCall; /* Index of the first 'call' instruction */
  152.     unsigned short LastCall;  /* Index of the last 'call' instruction */
  153.     unsigned short ChangedCounter;
  154.     unsigned short deleted;
  155. }BasicBlock;
  156. extern int GetLastFunctionLabel(void);
  157. static unsigned char *Nullst = "NULL";
  158. /*
  159. We keep the state of the machine in this character vector.
  160. Each position points towards a character string that
  161. indicates the contents of the register.
  162. */
  163. static unsigned char *State[25];
  164. static int deleted = 0,redundant = 0;
  165. static int lastLabel = 0;
  166. static int hasRegisterVariables;
  167. /*
  168. The peephole optimizer can be compiled as a standalone module. It
  169. will emit very verbose output...
  170. */
  171. #ifdef DEBUGOPTIM
  172. static unsigned char *buffer;
  173. #define Printf printf
  174. #define Printf1(a) printf(a)
  175. #define Printf2(a,b) printf(a,b)
  176. #define Printf3(a,b,c) printf(a,b,c)
  177. extern int hasAllocA;
  178. #else
  179. #define Printf1(a)
  180. #define Printf2(a,b)
  181. #define Printf3(a,b,c)
  182. extern int hasAllocA;
  183. #endif
  184. extern unsigned char *FindStringConstant(unsigned char *name);
  185.  
  186. #ifdef STANDALONE
  187. int hasAllocA = 0;
  188. main(int argc,char *argv[])
  189. {
  190.     FILE *f;
  191.     int l,nl;
  192.     unsigned char *newb;
  193.  
  194.     f = fopen(argv[1],"r");
  195.     if (f == NULL) {
  196.         fprintf(stderr,"Impossible to open %s\n",argv[1]);
  197.         return(1);
  198.     }
  199.     fseek(f,0,SEEK_END);
  200.     l = ftell(f);
  201.     fseek(f,0,SEEK_SET);
  202.     buffer = malloc(l+10);
  203.     memset(buffer,0,l+10);
  204.     l = fread(buffer,1,l,f);
  205.     fclose(f);
  206.     Printf("Optimizing %s\n",argv[1]);
  207.     nl = ScanAsm(buffer,l,&newb);
  208.     Printf("%d instructions deleted,redundant %d\n",deleted,redundant);
  209.     f = fopen("output.out","w");
  210.     fwrite(newb,1,nl,f);
  211.     fclose(f);
  212. }
  213. static int genlabel(int n)
  214. {
  215.     static int label = 99999;
  216.  
  217.     label += n;
  218.     return label - n;
  219. }
  220.  
  221. #endif
  222.  
  223. /*
  224. This routine searches the InstructionTable for an index where
  225. it will put the next changed instruction. Those instructions
  226. start at the end of the basic block.
  227. */
  228. static Instruction *GetNextChangedInstruction(Instruction *Ins,BasicBlock *bb)
  229. {
  230.     Instruction *insDst;
  231.  
  232.     if (bb->ChangedCounter  >= MAXINSTRUCTION) {
  233.         fprintf(stderr,"overflow of changed index in basic block %s\n",bb->Label);
  234.         exit(1);
  235.     }
  236.     Ins->Flags |= CHANGED;
  237.     Ins->ChangedIdx = bb->ChangedCounter;
  238.     insDst = &InstructionTable[bb->ChangedCounter];
  239.     bb->ChangedCounter++;
  240.     memset(insDst,0,sizeof(Instruction));
  241.     return(insDst);
  242. }
  243. static Instruction *ChangeInstruction(Instruction *ins,BasicBlock *bb,unsigned char *name,unsigned char *src,unsigned char *dst)
  244. {
  245.     Instruction *result;
  246.  
  247.     result = GetNextChangedInstruction(ins,bb);
  248.     strcpy(result->Name,name);
  249.     strcpy(result->src,src);
  250.     strcpy(result->dst,dst);
  251.     return(result);
  252. }
  253.  
  254. #ifdef STANDALONE
  255. /*
  256. This routine searches the start of the basic block. It looks
  257. for a label, that should start with the '_$' prefix. Change
  258. this if the prefix is different.
  259. */
  260. static unsigned char *FindBeginBlock(unsigned char *bp,BasicBlock *bb)
  261. {
  262.     if (*bp == '_' && bp[1] == '$') {
  263.         unsigned char *p;
  264.         p = bp+2;
  265.         while (*p && *p != '\n' && *p != ':') p++;
  266.         if (*p == ':') goto retgood;
  267.         if (*p == 0) return(NULL);
  268.     }
  269.     while (*bp) {
  270.         if (bp[0] == '\n' && bp[1] == '_') {
  271.             bp++;
  272.             if (bp[1] == '$') {
  273.                 int i;
  274. retgood:
  275.                 i = 0;
  276.                 while (*bp && *bp != '\n') bb->Label[i++] = *bp++;
  277.                 if (*bp == '\n') bp++;
  278.                 return(bp);
  279.             }
  280.             else {
  281.                 unsigned char *p = bp;
  282.  
  283.                 while (*p && *p != '\n') {
  284.                     if (*p == ':') {
  285.                         goto retgood;
  286.                     }
  287.                     else if (*p == ',') {
  288.                         bp = p;
  289.                         break;
  290.                     }
  291.                     p++;
  292.                 }
  293.             }
  294.         }
  295.         else if (*bp == '.' && bp[1] == 'd' && bp[2] == 'a' && bp[3] == 't') {
  296. scanfortext:
  297.             bp++;
  298.             for (;;) {
  299.                 while (*bp && *bp != '.')
  300.                     bp++;
  301.                 if (*bp == '.' && !strncmp(bp,".text",5))
  302.                     break;
  303.                 else if (*bp == 0) break;
  304.                 else if (*bp == '.') bp++;
  305.             }
  306.             if (bp == NULL) return(NULL);
  307.             if (*bp == 0) return(NULL);
  308.         }
  309.         else if (*bp == '.' && bp[1] == 'b' && bp[2] == 's' && bp[3] == 's')
  310.             goto scanfortext;
  311.         else bp++;
  312.     }
  313.     return(NULL);
  314. }
  315. #endif
  316. /* Converts a register name into a register number */
  317. static int GetRegNumber(unsigned char *name)
  318. {
  319.     register unsigned char *n = name;
  320.     if (*n == 'e') n++;
  321.     else if (*n == 'm' && n[1] == 'm') {
  322.         return MM0 + n[2] - '0';
  323.     }
  324.     else {
  325.         char tmp[3];
  326.         tmp[0] = 'e';
  327.         tmp[1] = *n++;
  328.         tmp[2] = (*n == 'l') ? 'x' : *n;
  329.         return(ESP+GetRegNumber(tmp));
  330.     }
  331.     switch (*n++) {
  332.         case 'a': return(EAX);
  333.         case 'b': return (*n == 'x')? EBX : EBP;
  334.         case 'c': return(ECX);
  335.         case 'd': return( *n == 'x')? EDX : EDI;
  336.         case 's': return (*n == 'i') ? ESI : ESP;
  337.     }
  338.     fprintf(stderr,"bad register name %c%c%c\n",name[0],name[1],name[2]);
  339.     exit(1);
  340.     return(0);
  341. }
  342.  
  343. /*
  344. Parser for one instruction. It separates the instruction into
  345. opcode (Name field), source and destination.
  346. */
  347. static unsigned char *AddNextInstruction(unsigned char *bp,BasicBlock *bb,unsigned char **pp)
  348. {
  349.     unsigned char *p,*start,*op;
  350.     int i,regcount,firstCodeChar;
  351.     Instruction *ins;
  352.  
  353.     start = p = bp;
  354.     if (*p == '_' && p[1] == '$') {
  355.         *pp = bp;
  356.         return(NULL);
  357.     }
  358.     if (*bp == 1) {
  359.         while (*bp == 1) bp++;
  360.     }
  361.     if (*bp == '\t') bp++;
  362.     if (*bp == ';')
  363.         goto skipline;
  364.     if (*bp == '.') {
  365.         if (!strncmp(bp,".data",5) || !strncmp(bp,".bss",4)) {
  366.             bp = strstr(bp,".text");
  367.             *pp = bp;
  368.             return(bp);
  369.         }
  370. skipline:
  371.         while (*bp && *bp != '\n') bp++;
  372.         if (*bp == '\n') bp++;
  373.         *pp = bp;
  374.         if (*bp == 0) return(NULL);
  375.         return(bp);
  376.     }
  377.     if (InstructionIndex < MAXINSTRUCTION-50) {
  378.         ins = &InstructionTable[InstructionIndex];
  379.         InstructionIndex++;
  380.         memset(ins,0,sizeof(Instruction));
  381.     }
  382.     else {
  383.         fprintf(stderr,"Basic block too big!\n");
  384.         return(NULL);
  385.     }
  386.     i = 0;
  387.     firstCodeChar = *bp;
  388.     if (firstCodeChar == 'j')
  389.         ins->Flags |= ISJUMP;
  390.     else if (firstCodeChar == 'f')
  391.         ins->Flags |= ISFLOAT;
  392.     op = ins->Name;
  393.     while (*bp >= 'a' && *bp <= 'z') {
  394.         if (i < 10)
  395.             op[i++] = *bp++;
  396.         if (i > 8) {
  397.             op[i] = 0;
  398.             fprintf(stderr,"overflow in instruction name %s ",ins->Name);
  399.             while (*bp && *bp != '\n') fprintf(stderr,"%c",*bp++);
  400.             fprintf(stderr,"\n");
  401.             exit(1);
  402.         }
  403.     }
  404.     ins->Start = start;
  405.     bb->NrOfInstructions++;
  406.     op[i] = 0;
  407.     if (i > 3 && firstCodeChar == 'm' && op[1] == 'o' &&
  408.         op[2] == 'v') {
  409.         if (op[3] == 'l') ins->Flags |= ISMOVL;
  410.         else if (op[3] == 's' && op[4] == 'b' && op[5] == 0) {
  411.             ins->Flags |= ISMOVSB;
  412.         }
  413.         else if (op[3] == 's' && (op[4] == 'w' || op[4] == 'b')
  414.             && op[5] == 'l') {
  415.             if (op[4] == 'w') ins->Flags |= ISMOVSWL;
  416.             else ins->Flags |= ISMOVSBL;
  417.         }
  418.         ins->Flags |= ISGENERICMOVE;
  419.     }
  420.     if (i == 3 && firstCodeChar == 'r' && op[1] == 'e' && op[2] == 't') {
  421.         while (*bp && *bp != '\n') bp++;
  422.         if (*bp == '\n') bp++;
  423.         *pp = bp;
  424.         ins->End = bp;
  425.         return(NULL);
  426.     }
  427.     if (i == 4 && firstCodeChar == 'l' && op[1] == 'e' &&
  428.         op[3] == 'l')
  429.         ins->Flags |= ISLEAL;
  430.     if (i == 4 && firstCodeChar == 'c' && op[2] == 'p'
  431.         && op[3] == 'l' && op[1] == 'm') {
  432.         ins->Flags |= ISCOMPARE;
  433.     }
  434.     while (*bp == ' ' || *bp == '\t') bp++;
  435.     if (*bp == '\n') {
  436.         bp++;
  437.         ins->End = bp;
  438.         *pp = bp;
  439.         return(bp);
  440.     }
  441.     i = regcount = 0;
  442.     if (*bp == '%') ins->Flags |= ISREGSRC;
  443.     while (*bp && *bp != ',') {
  444.         int c = *bp;
  445.         if (c == '\n') break;
  446.         if (i < MAXIDSIZE)
  447.             ins->src[i++] = c;
  448.         else ins->Flags |= TRUNCATED;
  449.         bp++;
  450.         if (c == '(') {
  451.             ins->Flags |= SRCOFFSET;
  452.             while (*bp && *bp != ')') {
  453.                 c = *bp++;
  454.                 if (i < 40)
  455.                     ins->src[i++] = c;
  456.                 if (c == ',') {
  457.                     ins->Flags |= SRCDEREFERENCE;
  458.                 }
  459.                 else if (c == '%') {
  460.                     int r;
  461.  
  462.                     r = GetRegNumber(bp);
  463.                     if (regcount == 0) ins->SrcReg = r;
  464.                     else ins->SrcReg |= (r << 8);
  465.                     regcount++;
  466.                 }
  467.             }
  468.             if (*bp == ')') ins->src[i++] = *bp++;
  469.         }
  470.         else if (c == '%') {
  471.             int r;
  472.  
  473.             r = GetRegNumber(bp);
  474.             if (regcount == 0) ins->SrcReg = r;
  475.             else ins->SrcReg |= (r << 8);
  476.             regcount++;
  477.         }
  478.         else if (c == '_') {
  479.             while (*bp && ((*bp >= 'a' && *bp <= 'z') || (*bp >= 'A' && *bp <= 'Z'))) {
  480.                 if (*bp == ',') break;
  481.                 if (i < MAXIDSIZE) {
  482.                     ins->src[i++] = *bp++;
  483.                 }
  484.                 else {
  485.                     ins->Flags |= TRUNCATED;
  486.                     bp++;
  487.                 }
  488.             }
  489.         }
  490.     }
  491.     if (*bp == ',' || (*bp == ' ' || *bp == '\t')) bp++;
  492.     else if (*bp == '\n'){
  493.         if (firstCodeChar == 'c' && op[1] == 'a') {
  494.             ins->Flags |= ISCALL;
  495.             bb->Flags |= ISCALL;
  496.             if (bb->FirstCall == 0)
  497.                 bb->FirstCall = (unsigned char)(InstructionIndex-1);
  498.             bb->LastCall = (unsigned char)(InstructionIndex-1);
  499.         }
  500.         bp++;
  501.         ins->End = bp;
  502.         return(bp);
  503.     }
  504.     while (*bp == ' ' || *bp == '\t') bp++;
  505.     if (*bp == '%') ins->Flags |= ISREGDST;
  506.     i = regcount = 0;
  507.     while (*bp && *bp != ' ' && *bp != '\n') {
  508.         int c = *bp++;
  509.         if (i < MAXIDSIZE)
  510.             ins->dst[i++] = (unsigned char)c;
  511.         else
  512.             ins->Flags |= TRUNCATED;
  513.         if (c == '(') {
  514.             ins->Flags |= DSTOFFSET;
  515.             while (*bp && *bp != ')') {
  516.                 c = *bp++;
  517.                 if (i < MAXIDSIZE)
  518.                     ins->dst[i++] = (unsigned char)c;
  519.                 else ins->Flags |= TRUNCATED;
  520.                 if (c == ',') {
  521.                     ins->Flags |= DSTDEREFERENCE;
  522.                 }
  523.                 else if (c == '%') {
  524.                     int r;
  525.  
  526.                     r = GetRegNumber(bp);
  527.                     if (regcount == 0) ins->DstReg = (unsigned char)r;
  528.                     else ins->DstReg |= (r << 8);
  529.                     regcount++;
  530.                 }
  531.             }
  532.             if (*bp == ')' && i < MAXIDSIZE) ins->dst[i++] = *bp++;
  533.             else if (i >= MAXIDSIZE) ins->Flags |= TRUNCATED;
  534.         }
  535.         else if (c == '%') {
  536.             int r;
  537.  
  538.             r = GetRegNumber(bp);
  539.             if (regcount == 0) ins->DstReg = r;
  540.             else ins->DstReg |= (r << 8);
  541.             regcount++;
  542.         }
  543.         else if (c == '_') {
  544.             while (*bp && ((*bp >= 'a' && *bp <= 'z') || (*bp >= 'A' && *bp <= 'Z'))) {
  545.                 if (*bp == ',') break;
  546.                 if (i < MAXIDSIZE) {
  547.                     ins->dst[i++] = *bp++;
  548.                 }
  549.                 else {
  550.                     ins->Flags |= TRUNCATED;
  551.                     bp++;
  552.                 }
  553.             }
  554.         }
  555.     }
  556.     while (*bp && *bp != '\n') bp++;
  557.     if (*bp == 0) {
  558.         ins->End = bp;
  559.         *pp = NULL;
  560.         return(NULL);
  561.     }
  562.     if (*bp == '\n') bp++;
  563.     ins->End = bp;
  564.     return(bp);
  565. }
  566.  
  567. /* Adds instructions to the basic block until it finds a label
  568. */
  569. static unsigned char *FindEndBlock(unsigned char *bp,BasicBlock *bb,unsigned char *stop)
  570. {
  571.     unsigned char *r=bp,*result;
  572.     bb->NrOfInstructions = 0;
  573.     while ((r=AddNextInstruction(r,bb,&result))!=NULL) {
  574.         if (InstructionIndex > 0
  575.             && InstructionTable[InstructionIndex-1].Flags & TRUNCATED) {
  576.             result = NULL;
  577.             bb->NrOfInstructions = 0;
  578.             fprintf(stderr,"Maximum identifier length exceeded.\n");
  579.             fprintf(stderr,"Quitting optimization\n");
  580.             return NULL;
  581.         }
  582.         if (r && r >= stop) break;
  583.     }
  584.     return(result);
  585. }
  586. #ifdef STANDALONE
  587. static unsigned char *FindBasicBlock(unsigned char *bp,BasicBlock *block,unsigned char *stop)
  588. {
  589.     unsigned char *bb,*be;
  590.  
  591.  
  592.     bb = FindBeginBlock(bp,block);
  593.     if (bb == NULL) return(NULL);
  594.     be = FindEndBlock(bb,block,stop);
  595.     return(be);
  596. }
  597. #endif
  598. /* Invalidates the contents of the given register ('which') if
  599.    they are equal to the given character string.
  600. */
  601. static void doclobber(unsigned char *p,int which)
  602. {
  603.     if (p == Nullst) return;
  604.     if (p == NULL) return;
  605.     if (which != EAX && State[EAX] && !strcmp(State[EAX],p)) {
  606.         Printf1("eax = NULL\n");
  607.         State[EAX] = Nullst;
  608.     }
  609.     if (which != EBX && State[EBX] && !strcmp(State[EBX],p)) {
  610.         Printf1("ebx = NULL\n");
  611.         State[EBX] = Nullst;
  612.     }
  613.     if (which != ECX && State[ECX] && !strcmp(State[ECX],p)) {
  614.         Printf1("ecx = NULL\n");
  615.         State[ECX] = Nullst;
  616.     }
  617.     if (which != EDX && State[EDX] && !strcmp(State[EDX],p)) {
  618.         Printf1("edx = NULL\n");
  619.         State[EDX] = Nullst;
  620.     }
  621.     if (which != ESI && State[ESI] && !strcmp(State[ESI],p)) {
  622.         Printf1("esi = NULL\n");
  623.         State[ESI] = Nullst;
  624.     }
  625.     if (which != EDI && State[EDI] && !strcmp(State[EDI],p)) {
  626.         Printf1("edi = NULL\n");
  627.         State[EDI] = Nullst;
  628.     }
  629. }
  630.  
  631. /* Replaces in the given buffer (str) the register named
  632.    'src' with the register named 'dst' and writes the
  633.    modified output into the 'out' buffer
  634. */
  635. static int doreplace(unsigned char *str,unsigned char *src,unsigned char *dst,unsigned char *out)
  636. {
  637.     unsigned char *p = str;
  638.     unsigned char *d = out;
  639.     int result = 0;
  640.  
  641.     while (*p) {
  642.         if (*p == '%') {
  643.             *d++ = *p++;
  644.             if (p[0] == src[0] && p[1] == src[1] && p[2] == src[2]) {
  645.                 *d++ = dst[0];
  646.                 *d++ = dst[1];
  647.                 *d++ = dst[2];
  648.                 p += 3;
  649.                 result++;
  650.             }
  651.             else if (p[0] != 'e') {
  652.                 if (p[0] == src[1] && p[1] == src[2]) {
  653.                     *d++ = dst[1];
  654.                     *d++ = dst[2];
  655.                     p += 2;
  656.                     result++;
  657.                 }
  658.                 else if (p[0] == src[1] && p[1] == 'l' && src[2] == 'x') {
  659.                     *d++ = dst[1];
  660.                     *d++ = 'l';
  661.                     p += 2;
  662.                 }
  663.             }
  664.         }
  665.         else *d++ = *p++;
  666.     }
  667.     *d = 0;
  668.     return(result);
  669. }
  670.  
  671. static int fixRegNr(int SrcReg,int reg,int oldreg)
  672. {
  673.     int r1,r2;
  674.  
  675.     if (SrcReg < ESP) return reg;
  676.     else if (SrcReg < SP) {
  677.         return reg + ESP;
  678.     }
  679.     else if (SrcReg & 0xFF00) {
  680.         r1 = SrcReg & 0xFF;
  681.         r2 = SrcReg >> 8;
  682.         if (oldreg == r1) {
  683.             return (reg | (r2 << 8));
  684.         }
  685.         else if (oldreg == r2) {
  686.             return ((reg << 8) | r1);
  687.         }
  688.         else
  689.             printf("internal compiler error 123 in optimizer\n");
  690.     }
  691.     return 0;
  692. }
  693.  
  694. static int ReplaceRegister(unsigned char *regsrc,unsigned char *regdst,BasicBlock *bb,int first,int last,int reg)
  695. {
  696.     Instruction *ins,*insDst;
  697.     unsigned char *src,*dst;
  698.     int dochanged,oldreg;
  699.  
  700.     ins = &InstructionTable[first];
  701.     if (ins->Flags & CHANGED) {
  702.         insDst = &InstructionTable[ins->ChangedIdx];
  703.         dst = insDst->dst;
  704.         src = insDst->src;
  705.     }
  706.     else {
  707.         dst = ins->dst;
  708.         src = ins->src;
  709.     }
  710.     ins->Flags |= CHANGED;
  711.     ins->ChangedIdx = bb->ChangedCounter;
  712.     insDst = &InstructionTable[bb->ChangedCounter];
  713.     bb->ChangedCounter++;
  714.     oldreg = GetRegNumber(regsrc);
  715.     memset(insDst,0,sizeof(Instruction));
  716.     if (!doreplace(dst,regsrc,regdst,insDst->dst)) {
  717.         bb->ChangedCounter--;
  718.         return(0);
  719.     }
  720.     ins->DstReg = reg;
  721.     strcpy(insDst->src,src);
  722.     strcpy(insDst->Name,ins->Name);
  723.     first++;
  724.     ins++;
  725.     while (first <= last) {
  726.         dochanged = 0;
  727.         if (ins->Flags & CHANGED) {
  728.             insDst = &InstructionTable[ins->ChangedIdx];
  729.             src = insDst->src;
  730.             dst = insDst->dst;
  731.         }
  732.         else {
  733.             src = ins->src;
  734.             dst = ins->dst;
  735.         }
  736.         insDst = GetNextChangedInstruction(ins,bb);
  737.         strcpy(insDst->Name,ins->Name);
  738.         if (doreplace(src,regsrc,regdst,insDst->src)) {
  739.             ins->SrcReg = fixRegNr(ins->SrcReg,reg,oldreg);
  740.             dochanged++;
  741.         }
  742.         if (first != last) {
  743.             if (doreplace(dst,regsrc,regdst,insDst->dst)) {
  744.                 ins->DstReg = fixRegNr(ins->DstReg,reg,oldreg);
  745.                 dochanged++;
  746.             }
  747.         }
  748.         else strcpy(insDst->dst,dst);
  749.         if (dochanged) {
  750.             ins->Flags |= CHANGED;
  751.         }
  752.         else {
  753.             bb->ChangedCounter--;
  754.             ins->Flags &= ~ CHANGED;
  755.         }
  756.         first++;
  757.         ins++;
  758.     }
  759.     bb->Registers[reg] = 1;
  760.     return(1);
  761. }
  762.  
  763. int testSafeReplacement(unsigned char *s)
  764. {
  765.     if (*s++ != '(') return 0;
  766.     if (*s++ != '%') return 0;
  767.     if (*s++ != 'e') return 0;
  768.     s += 2;
  769.     if (*s++ != ',') return 0;
  770.     if (*s++ != '%') return 0;
  771.     if (*s++ != 'e') return 0;
  772.     s += 2;
  773.     if (*s != ')') return 0;
  774.     return 1;
  775. }
  776.  
  777. static int AvoidClobber(unsigned char *reg,int idxInstruction,BasicBlock *bb)
  778. {
  779.     int i,n,lastidx;
  780.     Instruction *ins;
  781.  
  782.     if (State[ECX] != NULL && State[ECX] != Nullst) {
  783.         if (State[EDX] != NULL && State[EDX] != Nullst) {
  784.             return(0);
  785.         }
  786.     }
  787.     i = idxInstruction+1;
  788.     n = bb->NrOfInstructions;
  789.     if (i >= n) return(0);
  790.     ins = &InstructionTable[i];
  791.     lastidx = -1;
  792.     /* Find the first instruction that stores into that register */
  793.     while (i < n) {
  794.         if (ins->Flags & (CHANGED|ISCALL|TRUNCATED)) return(0);
  795.         if (ins->SrcReg > EBP || ins->DstReg > EBP) {
  796.             if (ins->SrcReg > EBP) {
  797.                 if (!testSafeReplacement(ins->src)) return 0;
  798.             }
  799.             if (ins->DstReg > EBP) {
  800.                 if (!testSafeReplacement(ins->dst)) return 0;
  801.             }
  802.         }
  803.         if (ins->Name[0] == 'f') return(0);
  804.         if (ins->Name[0] == 'i') {
  805.             if (!strncmp(ins->Name,"idiv",4)) return(0);
  806.             if (!strncmp(ins->Name,"imul",4)) return(0);
  807.         }
  808.         else if (!strncmp(ins->Name,"div",3)) return(0);
  809.         else if (!strncmp(ins->Name,"mul",3)) return(0);
  810.         if (ins->DstReg == ECX || ins->DstReg == EDX) return(0);
  811.         if (ins->SrcReg == EDX || ins->DstReg == ECX) return(0);
  812.         if (ins->dst[0] == '%') { /* if is a register store operation */
  813.             if (ins->Flags & ISGENERICMOVE)
  814.             if (ins->dst[1] == *reg && ins->dst[2] == reg[1] && ins->dst[3] == reg[2]) {
  815.                 if (ins->SrcReg > EBP) return(0);
  816.                 if (ins->dst[1] == ins->src[1] && ins->dst[2] == ins->src[2] &&
  817.                     ins->dst[3] == ins->src[3] && ins->src[0] == ins->dst[0]) {
  818.                     goto goon;
  819.                 }
  820.                 lastidx = i;
  821.                 break;
  822.             }
  823.         }
  824. goon:
  825.         i++;
  826.         ins++;
  827.     }
  828.     if (lastidx < 0) return(0);
  829.     if (State[ECX] == NULL || State[ECX] == Nullst) {
  830.         int r = ReplaceRegister(reg,"ecx",bb,idxInstruction,lastidx,ECX);
  831.         return (r)? ECX : 0;
  832.     }
  833.     if (State[EDX] == NULL || State[EDX] == Nullst) {
  834.         int r = ReplaceRegister(reg,"edx",bb,idxInstruction,lastidx,EDX);
  835.         return (r)? EDX : 0;
  836.     }
  837.     return(0);
  838. }
  839. static int IsAliveValue(BasicBlock *bb,int idx,int regNum)
  840. {
  841.     int i = idx,flags;
  842.     Instruction *ins = &InstructionTable[idx];
  843.  
  844.     if (hasRegisterVariables) {
  845.         if (regNum == ESI) return 1;
  846.         if (regNum == EBX) return 1;
  847.         if (regNum == EDI) return 1;
  848.     }
  849.     while (i < bb->NrOfInstructions) {
  850.         if (ins->SrcReg == regNum) return(1);
  851.         if (ins->SrcReg > EBP) return(1);
  852.         if (ins->DstReg > EBP) {
  853.             if (!(ins->DstReg == ESP && ins->src[0] == '$' && ins->Name[0] == 'a'))
  854.                 return(1);
  855.         }
  856.         flags = ins->Flags;
  857.         if ((flags & ISGENERICMOVE) == 0) {
  858.             if (ins->DstReg == regNum) {
  859.                 if (ins->Flags & ISLEAL) return(0);
  860.                 return(1);
  861.             }
  862.             if (ins->Flags & ISCOMPARE &&
  863.                 ins->SrcReg == regNum)
  864.                 return 1;
  865.             if (ins->Name[0] == 'o' && ins->Name[1] == 'r' &&
  866.                 ins->SrcReg == regNum)
  867.                 return 1;
  868.             if (ins->Name[0] == 'a' && ins->Name[1] == 'n' &&
  869.                 ins->SrcReg == regNum)
  870.                 return 1;
  871.         }
  872.         if (flags & ISCALL) {
  873.             if (regNum == EAX || regNum == ECX || regNum == EDX)
  874.                 return(0);
  875.         }
  876.         if (regNum == EAX || regNum == ECX) {
  877.             if (ins->Name[0] == 'i') {
  878.                 if (!strncmp(ins->Name,"idiv",4)) return(1);
  879.                 if (!strncmp(ins->Name,"imul",4)) return(1);
  880.             }
  881.             else if (!strncmp(ins->Name,"div",3)) return(1);
  882.             else if (!strncmp(ins->Name,"mul",3)) return(1);
  883.         }
  884.         if (!strcmp(ins->Name,"rep")) return(1);
  885.         if (!strncmp(ins->Name,"movs",4)
  886.             || !strncmp(ins->Name,"stos",4) || !strncmp(ins->Name,"scas",4)) {
  887.             return 1;
  888.         }
  889.         if (flags & ISGENERICMOVE) {
  890.             if (ins->dst[0] == '%' && ins->DstReg == regNum)
  891.                 return(0);
  892.             else if (ins->DstReg == regNum) return(1);
  893.         }
  894.         ins++;
  895.         i++;
  896.     }
  897.     return(0);
  898. }
  899.  
  900. static int isUsedInBlock(int idxInstruction,unsigned char *old,BasicBlock *bb,int aReg)
  901. {
  902.     int c = *old;
  903.     Instruction *ins;
  904.     int result = 0;
  905.  
  906.     ins = &InstructionTable[idxInstruction];
  907.     while (idxInstruction < bb->NrOfInstructions) {
  908.         if (c == ins->src[0] && !strcmp(ins->src,old)) {
  909.             result++;
  910.         }
  911.         if (c == ins->dst[0] && !strcmp(ins->dst,old)) {
  912.             if (strcmp(ins->Name,"cmpl"))
  913.                 return(result);
  914.             else result++;
  915.         }
  916.         if (ins->Flags & (ISCALL|CHANGED)) return(0);
  917.         if (ins->DstReg == ECX || ins->DstReg == EDX)
  918.             return(0);
  919.         if (ins->SrcReg == ECX || ins->SrcReg == EDX)
  920.             return(0);
  921.         if (ins->Name[2] == 'q' && ins->Name[1] == 'd')
  922.             return(0);
  923.         if (ins->Name[0] == 'r' && ins->Name[1] == 'e' && ins->Name[2] == 'p')
  924.             return(0);
  925.         if (ins->Name[0] == 's' && ins->Name[1] == 'h' && ins->Name[3] == 'l')
  926.             return(0);
  927.         if (ins->src[0] == '%' && ins->src[1] == 'c')
  928.             return(0);
  929.         if (ins->dst[0] == '%' && (ins->Flags & ISGENERICMOVE) && ins->DstReg == aReg) {
  930.             if (ins->SrcReg != aReg)
  931.                 break;
  932.         }
  933.         ins++;
  934.         idxInstruction++;
  935.     }
  936.     return(result);
  937. }
  938.  
  939. static int TestIfReturnFalse(Instruction *nextIns,int regNum)
  940. {
  941.     nextIns++;
  942.     if (!strcmp(nextIns->Name,"jne")) {
  943.         nextIns++;
  944.         if (nextIns->Flags & ISMOVL) {
  945.             if (nextIns->src[0] == '$' && nextIns->src[1] == '0'
  946.                 && nextIns->src[2] == 0) {
  947.                 if (nextIns->dst[0] == '%' && nextIns->DstReg == regNum) {
  948.                     nextIns->Flags |= DELETED;
  949.                     Printf1("Optimization 12\n");
  950.                     return(1);
  951.                 }
  952.             }
  953.         }
  954.     }
  955.     return(0);
  956. }
  957.  
  958. static void ChangeRedundantLoad(Instruction *ins,int regNum,BasicBlock *bb,int idxInstruction,int changeFlag)
  959. {
  960.     unsigned char *regname,tbuf[60];
  961.     Instruction *insDst,*nextIns;
  962.     int SrcReg;
  963.  
  964.     nextIns = &InstructionTable[idxInstruction+1];
  965.     regname = RegisterNames[regNum];
  966.     if (hasRegisterVariables) goto skipOptims;
  967.     if (nextIns->Flags & (CHANGED|DELETED)) goto skipOptims;
  968.     if (nextIns->Flags & (ISGENERICMOVE|ISLEAL)) {
  969.         SrcReg = nextIns->SrcReg;
  970.         if (nextIns->Flags & ISLEAL) {
  971.             if (nextIns->DstReg == ins->DstReg) {
  972.                 if (SrcReg > SP) {
  973.                     if (((SrcReg & 0xFF) == ins->DstReg) ||
  974.                         (((SrcReg >> 8)&0xFF) == ins->DstReg)) {
  975.                         SrcReg = ins->DstReg;
  976.                         if (doreplace(nextIns->src,RegisterNames[SrcReg],RegisterNames[regNum],tbuf))  {
  977.                             ins->Flags |= DELETED;
  978.                             deleted++;
  979.                             redundant--;
  980.                             insDst = ChangeInstruction(nextIns,bb,nextIns->Name,tbuf,nextIns->dst);
  981.                             SrcReg = nextIns->SrcReg;
  982.                             if ((SrcReg & 0xFF) == ins->DstReg) {
  983.                                 regNum = ((SrcReg&0xFF)|regNum);
  984.                             }
  985.                             else {
  986.                                 regNum = (regNum << 8) | (SrcReg >> 8);
  987.                             }
  988.                             nextIns->SrcReg = regNum;
  989.                             Printf1("Optimization Nr 10\n");
  990.                             return;
  991.                         }
  992.                     }
  993.                 }
  994.             }
  995.         }
  996.         /*
  997.             Try to catch sequences like:
  998.                 movl    %edi,      -4(%ebp)
  999.                 .
  1000.                 .
  1001.                 .
  1002.                 movl    -4(%ebp),  %esi deleted
  1003.                   movswl  50(%esi),  %esi Replace by: movswl   50(%edi), %esi
  1004.             The rationale is that it is not worth to move a register into another,
  1005.             if that register will be used both as source and destination.
  1006.             Replace the source by the register, sparing one instruction.
  1007.             N.B. This will produce a wonderful BUG if the test is not done
  1008.             for a sequence like:
  1009.                 movl -8(%ebp),%edi                       deleted
  1010.                 movl %edi,(,%edi)    movl        %eax,     (,%edi)
  1011.  
  1012.             Since -8(%ebp) was in %eax, the deleting of the first
  1013.             instruction will use whatever was in edi before!!!
  1014.             This will happen when you assign a member of a structure to
  1015.             itself, for instance
  1016.                 structure->Next = structure;
  1017.             to make a circular list.
  1018.  
  1019.         */
  1020.         if (nextIns->SrcReg == ins->DstReg &&
  1021.             nextIns->DstReg == ins->DstReg
  1022.             && ins->DstReg < EBP
  1023.             && ((nextIns->Flags & DSTDEREFERENCE)==0)) {
  1024.             if (doreplace(nextIns->src,RegisterNames[SrcReg],RegisterNames[regNum],tbuf))  {
  1025.                 ins->Flags |= DELETED;
  1026.                 State[ins->DstReg] = Nullst;
  1027.                 deleted++;
  1028.                 redundant--;
  1029.                 insDst = ChangeInstruction(nextIns,bb,nextIns->Name,tbuf,nextIns->dst);
  1030.                 nextIns->SrcReg = regNum;
  1031.                 Printf1("Optimization Nr 9\n");
  1032.                 return;
  1033.             }
  1034.         }
  1035.         if ((nextIns->Flags & CHANGED) == 0 &&
  1036.             ins->DstReg < EBP &&
  1037.             nextIns->DstReg == ins->DstReg && !IsAliveValue(bb,idxInstruction+1,ins->DstReg)) {
  1038.             if (doreplace(nextIns->dst,RegisterNames[nextIns->DstReg],RegisterNames[regNum],tbuf))  {
  1039.                 ins->Flags |= DELETED;
  1040.                 deleted++;
  1041.                 redundant--;
  1042.                 insDst = ChangeInstruction(nextIns,bb,nextIns->Name,nextIns->src,tbuf);
  1043.                 State[ins->DstReg] = Nullst;
  1044.                 nextIns->DstReg = regNum;
  1045.                 Printf1("Optimization 9.1\n");
  1046.                 return;
  1047.             }
  1048.         }
  1049. #if 1
  1050.         /* Replace
  1051.             movl %eax,%edi
  1052.             movl %edi,-24(%ebp)
  1053.  
  1054.             with
  1055.             movl %eax,-24(%ebp)
  1056.  
  1057.         */
  1058.         else if (nextIns->SrcReg == ins->DstReg && (ins->Flags & ISREGDST) &&
  1059.                 (nextIns->Flags & CHANGED) == 0 &&
  1060.                 ins->DstReg < EBP &&
  1061.                 (ins->Flags & ISMOVL) &&
  1062.                 (nextIns->Flags & ISMOVL) && (nextIns->Flags & ISREGSRC)) {
  1063.             if (!IsAliveValue(bb,idxInstruction+2,ins->DstReg)) {
  1064.                 sprintf(tbuf,"%%%s",regname);
  1065.                 insDst = ChangeInstruction(nextIns,bb,nextIns->Name,tbuf,nextIns->dst);
  1066.                 nextIns->SrcReg = regNum;
  1067.                 ins->Flags |= DELETED;
  1068.                 deleted++;
  1069.                 redundant--;
  1070.                 State[ins->DstReg] = Nullst;
  1071.                 Printf1("Optimization 18\n");
  1072.                 return;
  1073.             }
  1074.         }
  1075. #endif
  1076.         else if (nextIns->src[0] == '$' && nextIns->DstReg == ins->DstReg) {
  1077.             insDst = nextIns + 1;
  1078.             if ((insDst->Flags & ISMOVL) &&
  1079.                 ins->DstReg < EBP &&
  1080.                 (insDst->Flags & ISREGDST)
  1081.                 && insDst->DstReg == ins->DstReg) {
  1082.                 if (doreplace(nextIns->dst,RegisterNames[nextIns->DstReg],RegisterNames[regNum],tbuf))  {
  1083.                     ins->Flags |= DELETED;
  1084.                     deleted++;
  1085.                     redundant--;
  1086.                     State[ins->DstReg] = Nullst;
  1087.                     insDst = ChangeInstruction(nextIns,bb,nextIns->Name,nextIns->src,tbuf);
  1088.                     nextIns->SrcReg = regNum;
  1089.                     Printf1("Optimization Nr 14\n");
  1090.                     return;
  1091.                 }
  1092.             }
  1093.         }
  1094.     }
  1095.     /* Replace sequences like
  1096.         cmpl $0,%esi
  1097.         by
  1098.         or   %esi,%esi
  1099.         that is shorter
  1100.     */
  1101.     else if (nextIns->src[0] == '$' && nextIns->src[1] == '0' && nextIns->src[2] == 0) {
  1102.         if (nextIns->Flags & ISCOMPARE && nextIns->dst[0] == '%') {
  1103.             if (nextIns->DstReg == ins->DstReg && !IsAliveValue(bb,idxInstruction+2,ins->DstReg)) {
  1104.                 ins->Flags |= DELETED;
  1105.                 deleted++;
  1106.                 redundant--;
  1107.                 sprintf(tbuf,"%%%s",regname);
  1108.                 insDst = ChangeInstruction(nextIns,bb,"or",tbuf,tbuf);
  1109.                 Printf1("Optimization Nr 11\n");
  1110.                 TestIfReturnFalse(nextIns,regNum);
  1111.                 return;
  1112.             }
  1113.         }
  1114.     }
  1115.     /* Try to catch sequences like
  1116.         movl %eax,%edi
  1117.         cmpl $45, %edi
  1118.  
  1119.         and replace them with
  1120.         cmpl $45,%eax
  1121.     */
  1122.     else if ((nextIns->Flags & (CHANGED|DELETED)) == 0 &&
  1123.             (nextIns->Flags & ISCOMPARE) &&
  1124.             ins->DstReg < EBP &&
  1125.              nextIns->src[0] == '$' && nextIns->dst[0] == '%' &&
  1126.              !strcmp(nextIns->dst,ins->dst) && !IsAliveValue(bb,idxInstruction+2,ins->DstReg)) {
  1127.         sprintf(tbuf,"%%%s",regname);
  1128.         insDst = ChangeInstruction(nextIns,bb,nextIns->Name,nextIns->src,tbuf);
  1129.         ins->Flags |= DELETED;
  1130.         nextIns->DstReg = regNum;
  1131.         State[ins->DstReg] = Nullst;
  1132.         Printf1("Optimization 17\n");
  1133.         deleted++;
  1134.         redundant--;
  1135.         return;
  1136.     }
  1137.     /* Try to change a sequence of instructions like:
  1138.         movl %eax,%edi
  1139.         cmpl %edi,-4(%ebp)
  1140.  
  1141.         into
  1142.  
  1143.         cmpl %eax,-4(%ebp)
  1144.         Conditions:
  1145.             1. Do not mess with already changed instructions (too complex)
  1146.             2. Must be a compare operation
  1147.             3. The source must be a register
  1148.             4. That register should be the same that is being moved
  1149.     */
  1150.     else if ((nextIns->Flags & CHANGED)==0 &&
  1151.         ins->DstReg < EBP &&
  1152.         (nextIns->Flags & ISCOMPARE) && nextIns->src[0] == '%' &&
  1153.             nextIns->SrcReg == ins->DstReg) {
  1154.         sprintf(tbuf,"%%%s",regname);
  1155.         insDst = ChangeInstruction(nextIns,bb,nextIns->Name,tbuf,nextIns->dst);
  1156.         ins->Flags |= DELETED;
  1157.         deleted++;
  1158.         redundant--;
  1159.         State[ins->DstReg] = Nullst;
  1160.         Printf1("Optimization 15\n");
  1161.         return;
  1162.  
  1163.     }
  1164.     else if ((nextIns->Flags & CHANGED)== 0 &&
  1165.         !strcmp(nextIns->Name,"addl") &&
  1166.         ins->DstReg < EBP &&
  1167.              nextIns->src[0] == '$' &&  nextIns->DstReg == ins->DstReg &&
  1168.              nextIns->dst[0] == '%' && ins->dst[0] == '%') {
  1169.     /* Try to change a sequence of instructions like:
  1170.         movl %eax,%edi
  1171.         addl $5,%edi
  1172.  
  1173.         into
  1174.  
  1175.         leal 5(%eax),%edi
  1176.         Conditions:
  1177.             1. Do not mess with already changed instructions (too complex)
  1178.             2. Must be a addl operation
  1179.             3. The source must be an immediate
  1180.             4. The destination register should be the same as the source register
  1181.     */
  1182.         sprintf(tbuf,"%s(%%%s)",nextIns->src+1,regname);
  1183.         insDst = ChangeInstruction(nextIns,bb,"leal",tbuf,ins->dst);
  1184.         nextIns->Flags |= ISLEAL;
  1185.         nextIns->SrcReg = regNum;
  1186.         nextIns->DstReg = ins->DstReg;
  1187.         ins->Flags |= DELETED;
  1188.         deleted++;
  1189.         redundant--;
  1190.         State[ins->DstReg] = Nullst;
  1191.         Printf1("Optimization 16\n");
  1192.         return;
  1193.  
  1194.     }
  1195.     /*
  1196.         Try to substitute
  1197.         mov %eax,%edi
  1198.         push %edi
  1199.  
  1200.         with
  1201.         push %eax
  1202.     */
  1203.     else if ((ins->Flags & ISMOVL) &&
  1204.         (nextIns->Flags & (CHANGED|DELETED)) == 0 && nextIns->Name[0] == 'p' &&
  1205.              nextIns->Name[1] == 'u' && nextIns->src[0] == '%' &&
  1206.              nextIns->SrcReg == ins->DstReg) {
  1207.         if (!IsAliveValue(bb,idxInstruction+2,ins->DstReg)) {
  1208.             sprintf(tbuf,"%%%s",regname);
  1209.             insDst = ChangeInstruction(nextIns,bb,nextIns->Name,tbuf,"");
  1210.             ins->Flags |= DELETED;
  1211.             deleted++;
  1212.             redundant--;
  1213.             State[ins->DstReg] = Nullst;
  1214.             Printf1("Optimization 18\n");
  1215.             return;
  1216.         }
  1217.     }
  1218. skipOptims:
  1219.     if (!changeFlag) return;
  1220.     if (strlen(ins->src) <4) return;
  1221.     if (ins->DstReg > EBP) return;
  1222.     if (strcmp(ins->Name,"movl")) {
  1223.         /*
  1224.             We can use this byte widening instructions only with memory
  1225.             references. I assume that the compiler widens the arguments always
  1226.             before loading a register with a 16 or 8 bit value, a safe
  1227.             assumption I suppose.
  1228.         */
  1229. //        strcpy(insDst->Name,"movl"); /*++++++++++++++++++*/
  1230.         return;
  1231.     }
  1232. //    else    strcpy(insDst->Name,ins->Name);
  1233.     insDst = GetNextChangedInstruction(ins,bb);
  1234.     strcpy(insDst->Name,ins->Name);
  1235.     /* Print the regname into the source of the changed instruction */
  1236.     sprintf(tbuf,"%%%s",regname);
  1237.     strcpy(insDst->src,tbuf);
  1238.     /* The destination doesn't change */
  1239.     strcpy(insDst->dst,ins->dst);
  1240.     /* Update flags etc */
  1241.     ins->SrcReg = regNum;
  1242.     Printf1("Optimization 5\n");
  1243. }
  1244.  
  1245. static int ReadValue(unsigned char *src)
  1246. {
  1247.     int result,r;
  1248.  
  1249.     if (src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) {
  1250.         r = sscanf(src+2,"%x",&result);
  1251.     }
  1252.     else {
  1253.         r = sscanf(src,"%d",&result);
  1254.     }
  1255.     if (r) return(result);
  1256.     return(0);
  1257. }
  1258.  
  1259. static Instruction *GetLastInstruction(int idxInstruction)
  1260. {
  1261.     int li = idxInstruction;
  1262.     Instruction *lastIns = NULL;
  1263.  
  1264.     do {
  1265.         li--;
  1266.         lastIns = &InstructionTable[li];
  1267.     } while (li >= 0 && (lastIns->Flags & DELETED));
  1268.     if (li >= 0) return(lastIns);
  1269.     return(NULL);
  1270. }
  1271. #if 1
  1272. static int CheckValueAlreadyLoaded(unsigned char *p)
  1273. {
  1274.     if (State[EAX] && !strcmp(State[EAX],p)) {
  1275.         return(EAX);
  1276.     }
  1277.     if (State[EBX] && !strcmp(State[EBX],p)) {
  1278.         return(EBX);
  1279.     }
  1280.     if (State[ECX] && !strcmp(State[ECX],p)) {
  1281.         return(ECX);
  1282.     }
  1283.     if (State[EDX] && !strcmp(State[EDX],p)) {
  1284.         return(EDX);
  1285.     }
  1286.     if (State[ESI] && !strcmp(State[ESI],p)) {
  1287.         return(ESI);
  1288.     }
  1289.     if (State[EDI] && !strcmp(State[EDI],p)) {
  1290.         return(EDI);
  1291.     }
  1292.     return(0);
  1293. }
  1294. #endif
  1295. void FixCalls(Instruction *ins,BasicBlock *bb,int idxInstruction)
  1296. {
  1297.     int last,i,first;
  1298.  
  1299.     ins->Flags &= ~ISCALL;
  1300.     if (idxInstruction == bb->LastCall) {
  1301.         if (bb->FirstCall == idxInstruction) {
  1302.             bb->FirstCall = bb->LastCall = 0;
  1303.             return;
  1304.         }
  1305.         last = bb->FirstCall;
  1306.         for (i=bb->FirstCall+1;i<idxInstruction-1;i++) {
  1307.             if (InstructionTable[i].Flags & ISCALL)
  1308.                 last = i;
  1309.         }
  1310.         if (last == bb->FirstCall) {
  1311.             bb->FirstCall = bb->LastCall = 0;
  1312.             return;
  1313.         }
  1314.         bb->LastCall = last;
  1315.         return;
  1316.     }
  1317.     if (idxInstruction == bb->FirstCall) {
  1318.         if (bb->LastCall == idxInstruction) {
  1319.             bb->FirstCall = bb->LastCall = 0;
  1320.             return;
  1321.         }
  1322.         first = 0;
  1323.         for (i=bb->FirstCall+1;i<bb->LastCall;i++) {
  1324.             if (InstructionTable[i].Flags & ISCALL) {
  1325.                 first = i;
  1326.                 break;
  1327.             }
  1328.         }
  1329.         bb->FirstCall = first;
  1330.         if (first == 0) bb->LastCall = 0;
  1331.         return;
  1332.     }
  1333. }
  1334. static char tbuf[70];
  1335. static unsigned char *src;
  1336. static unsigned char *dst;
  1337. static unsigned char *opcode;
  1338. static unsigned char *old,*savesrc;
  1339. static int regdst,regsrc,isImmediate;
  1340. static int aReg,isMovl,isRedundant;
  1341. static Instruction *insDst,*lastIns,*changedInstruction,*nextIns;
  1342. static Instruction *ins;
  1343. static BasicBlock *bb;
  1344. static int idxInstruction;
  1345.  
  1346. static int RegToRegCopy(void)
  1347. {
  1348. #if 1
  1349.     /* Replace
  1350.     movl %eax,%edi
  1351.     movl %edi,-24(%ebp)
  1352.  
  1353.     with
  1354.     movl %eax,-24(%ebp)
  1355.  
  1356.     */
  1357.     if (nextIns->SrcReg == ins->DstReg &&
  1358.         ins->DstReg != EAX &&
  1359.        (nextIns->Flags & CHANGED) == 0 && !strcmp(ins->Name,"movl") &&
  1360.        !strcmp(nextIns->Name,"movl") && nextIns->src[0] == '%') {
  1361.        if (!IsAliveValue(bb,idxInstruction+2,ins->DstReg)) {
  1362.           insDst = ChangeInstruction(nextIns,bb,nextIns->Name,ins->src,nextIns->dst);
  1363.           nextIns->SrcReg = ins->SrcReg;
  1364.           ins->Flags |= DELETED;
  1365.           deleted++;
  1366.           Printf1("Optimization 18\n");
  1367. //          printf("1:\t%s\t%s\t%s\n2:\t%s\t%s\t%s\n3:\t%s\t%s\t%s\n",ins->Name,ins->src,ins->dst,
  1368. //            nextIns->Name,nextIns->src,nextIns->dst,insDst->Name,insDst->src,insDst->dst);
  1369.           State[ins->SrcReg] = nextIns->dst;
  1370.           return 2;
  1371.        }
  1372.     }
  1373.     return 0;
  1374. #endif
  1375.    /* Try to catch sequences like
  1376.          movl %eax,%edi
  1377.          cmpl $45, %edi
  1378.          and replace them with
  1379.          cmpl $45,%eax
  1380.    */
  1381.    if ((nextIns->Flags & CHANGED) == 0 && (nextIns->Flags & ISCOMPARE) &&
  1382.         nextIns->src[0] == '$' && nextIns->dst[0] == '%' &&
  1383.         nextIns->DstReg != EAX &&
  1384.         !strcmp(nextIns->dst,ins->dst) &&
  1385.         !IsAliveValue(bb,idxInstruction+2,ins->DstReg)) {
  1386.         insDst = ChangeInstruction(nextIns,bb,nextIns->Name,nextIns->src,ins->src);
  1387.         ins->Flags |= DELETED;
  1388.         nextIns->DstReg = ins->SrcReg;
  1389.         Printf1("Optimization 17\n");
  1390.         deleted++;
  1391.         return 1;
  1392.     }
  1393.     return 0;
  1394. }
  1395.  
  1396.  
  1397. static int compare(void)
  1398. {
  1399.     int reg;
  1400.  
  1401.     if (ins->Flags & (CHANGED|DELETED))
  1402.         return 1;
  1403.     /*
  1404.         replace
  1405.         cmpl $0,reg
  1406.         by
  1407.         or reg,reg
  1408.     */
  1409.     if (regdst && !regsrc && isImmediate && src[1] == '0' && src[2] == 0) {
  1410.         sprintf(tbuf,"%%%s",dst);
  1411.         ChangeInstruction(ins,bb,"or",tbuf,tbuf);
  1412.         Printf1("compl->or\n");
  1413.         TestIfReturnFalse(ins,ins->DstReg);
  1414.         return(1);
  1415.     }
  1416.     else
  1417.     if (regdst /*&& isImmediate*/ && idxInstruction > 1) {
  1418.         /*
  1419.             movl -4(%ebp),%esi
  1420.             cmpl $45,%esi
  1421.                 to
  1422.             cmpl $45,-4(%ebp)
  1423.         */
  1424.         lastIns = GetLastInstruction(idxInstruction);
  1425.         if (isImmediate &&
  1426.             !hasRegisterVariables &&
  1427.             lastIns && (lastIns->Flags & ISREGDST) &&
  1428.             (lastIns->Flags & (CHANGED|DELETED)) == 0 &&
  1429.             (lastIns->Flags & ISMOVL) &&
  1430.             lastIns->DstReg == ins->DstReg    &&
  1431.             (lastIns->Flags & ISREGSRC) == 0 &&
  1432.             !IsAliveValue(bb,idxInstruction+1,ins->DstReg)) {
  1433.             ChangeInstruction(ins,bb,opcode,ins->src,lastIns->src);
  1434.             lastIns->Flags |= DELETED;
  1435.             if (ins->DstReg < EBP)
  1436.                 State[ins->DstReg] = NULL;
  1437.             deleted++;
  1438.             Printf1("Optimization 19\n");
  1439.             return(1);
  1440.         }
  1441.         /*
  1442.         movl    116(%esi),%esi
  1443.         cmpl    %esi,%edi
  1444.         to
  1445.         cmpl    116(%esi),%edi
  1446.         savings: two bytes
  1447.         */
  1448.         if (regsrc &&
  1449.             !isImmediate &&
  1450.             !hasRegisterVariables &&
  1451.             lastIns && (lastIns->Flags & ISREGDST) &&
  1452.             (lastIns->Flags & (CHANGED|DELETED)) == 0 &&
  1453.             (lastIns->Flags & ISMOVL) &&
  1454.             lastIns->DstReg == ins->SrcReg    &&
  1455.             (lastIns->Flags & ISREGSRC) == 0 &&
  1456.             !IsAliveValue(bb,idxInstruction+1,lastIns->DstReg)) {
  1457.             ChangeInstruction(ins,bb,opcode,lastIns->src,ins->dst);
  1458.             lastIns->Flags |= DELETED;
  1459.             deleted++;
  1460.             State[ins->SrcReg] = Nullst;
  1461.             Printf1("Optimization 48\n");
  1462.             return(1);
  1463.         }
  1464.     }
  1465.     if (!regdst /*&& isImmediate*/ && ins->Name[3] == 'l') {
  1466.         reg = CheckValueAlreadyLoaded(ins->dst);
  1467.         if (reg) {
  1468.             sprintf(tbuf,"%%%s",RegisterNames[reg]);
  1469.             if (isImmediate && ins->src[1] == '0' && ins->src[2] == 0) {
  1470.                 ChangeInstruction(ins,bb,"orl",tbuf,tbuf);
  1471.             }
  1472.             else ChangeInstruction(ins,bb,ins->Name,ins->src,tbuf);
  1473.             Printf1("Optimization 44\n");
  1474.         }
  1475.     }
  1476.     return 1;
  1477. }
  1478.  
  1479. static int inlinestrlen(void)
  1480. {
  1481.     Instruction *i1,*ip,*in;
  1482.     int condition;
  1483.  
  1484.     ip = NULL;
  1485.     /* i1 is the previous instruction. Should be a push of the
  1486.        argument of strlen */
  1487.     i1 = &InstructionTable[idxInstruction-1];
  1488.     if (i1->Flags & (CHANGED|DELETED)) return 0;
  1489.     /* in is the next instruction after the call. Should be an addl */
  1490.     in = &InstructionTable[idxInstruction+1];
  1491.     if (idxInstruction > 1)
  1492.         ip = &InstructionTable[idxInstruction-2];
  1493.     if (i1->Name[0] == 'p'
  1494.         && in->Name[0] == 'a') {
  1495.         if (State[EDI] == NULL)
  1496.             condition = 0;
  1497.         else
  1498.             condition = IsAliveValue(bb,idxInstruction+2,EDI);
  1499.         if (!ediIsSaved) condition = 1;
  1500.         insDst = GetNextChangedInstruction(i1,bb);
  1501.         strcpy(insDst->Name,"movl");
  1502.         strcpy(insDst->src,i1->src);
  1503.         if (condition) {
  1504.             strcpy(insDst->dst,"%edx\n");
  1505.             if (strcmp(i1->src,"%edi")) {
  1506.                 strcat(insDst->dst,"\txchg\t%edx,%edi");
  1507.             }
  1508.             State[EDX] = Nullst;
  1509.         }
  1510.         else {
  1511.             strcpy(insDst->dst,"%edi");
  1512.             State[EDI] = Nullst;
  1513.         }
  1514.         changedInstruction = GetNextChangedInstruction(insDst,bb);
  1515.         insDst->Flags &= ~CHANGED;
  1516.         insDst->Flags |= ADDED;
  1517.         strcpy(changedInstruction->Name,"\txor\t%eax");
  1518.         strcpy(changedInstruction->src,",%eax\n\tstc\n\tsbb\t%ecx,%ecx\n\trepne\n\t");
  1519.         strcpy(changedInstruction->dst,"scasb\n\tneg\t%ecx\n\tleal\t-2(%ecx),%eax\n");
  1520.         /* This overflows by 1 byte. Since the next field of the
  1521.            instruction is the 'Start' field and it is unused, we can
  1522.            do that... */
  1523.         if (condition)
  1524.             strcat(changedInstruction->dst,"\tmovl\t%edx,%edi\n");
  1525.         else State[EDI] = Nullst;
  1526.         State[EAX] = Nullst;
  1527.  
  1528.         in->Flags |= DELETED;
  1529.         ins->Flags |= DELETED;
  1530.         FixCalls(ins,bb,idxInstruction);
  1531.         deleted += 2;
  1532.         return(2);
  1533.     }
  1534.     return 0;
  1535. }
  1536.  
  1537. static int call(void)
  1538. {
  1539.     int i;
  1540.  
  1541.     if (recursion == 0 && !strcmp(savesrc,"_strlen")) {
  1542.         i = inlinestrlen();
  1543.         if (i)    return i;
  1544.     }
  1545.  
  1546.     else if (recursion == 0 && idxInstruction > 1 &&
  1547.         InstructionTable[idxInstruction-1].Name[0] == 'f' &&
  1548.         (!strcmp(savesrc,"_sqrt") || !strcmp(savesrc,"_sin") ||
  1549.             !strcmp(savesrc,"_fabs") ||
  1550.             !strcmp(savesrc,"_cos"))) {
  1551.         Instruction *i1,*i2,*i3;
  1552.  
  1553.         i1 = &InstructionTable[idxInstruction-1];
  1554.         i2 = &InstructionTable[idxInstruction-2];
  1555.         i3 = &InstructionTable[idxInstruction+1];
  1556.         if (!strcmp(i1->Name,"fstpl") &&
  1557.             !strcmp(i2->Name,"subl") &&
  1558.             !strcmp(i3->Name,"addl")) {
  1559.             i1->Flags |= DELETED;
  1560.             deleted++;
  1561.             i2->Flags |= DELETED;
  1562.             deleted++;
  1563.             if (!strcmp(savesrc,"_sqrt"))
  1564.                 insDst = ChangeInstruction(ins,bb,"fsqrt","","");
  1565.             else
  1566.             if (!strcmp(savesrc,"_sin"))
  1567.                 insDst = ChangeInstruction(ins,bb,"fsin","","");
  1568.             else
  1569.             if (!strcmp(savesrc,"_cos"))
  1570.                 insDst = ChangeInstruction(ins,bb,"fcos","","");
  1571.             else
  1572.             if (!strcmp(savesrc,"_fabs"))
  1573.                 insDst = ChangeInstruction(ins,bb,"fabs","","");
  1574.             i3->Flags |= DELETED;
  1575.             deleted++;
  1576.             FixCalls(ins,bb,idxInstruction);
  1577.             return(2);
  1578.         }
  1579.     }
  1580. #if 0
  1581.     else
  1582.     if (/*recursion == 0 && ediIsSaved && esiIsSaved &&*/ !strncmp(savesrc,"_strcpy",7)) {
  1583.         unsigned char *strconstant;
  1584.         Instruction *i1,*i2,*in;
  1585.         int ix,len;
  1586.  
  1587.         ix = idxInstruction-1;
  1588.         i1 = &InstructionTable[ix--];
  1589.         if (i1->Flags & (CHANGED|DELETED)) goto skip1;
  1590.         i2 = &InstructionTable[ix--];
  1591.         if (i2->Flags & (CHANGED|DELETED)) goto skip1;
  1592.         if (i2->Name[0] == 'l' && !strcmp(i2->Name,"leal")) {
  1593.             if ((InstructionTable[ix].Flags & CHANGED) == 0) {
  1594.                 i2 = &InstructionTable[ix--];
  1595.                 if (i2->Name[0] == 'i' && !strcmp(i2->Name,"imul")) {
  1596.                     i2 = &InstructionTable[ix--];
  1597.                 }
  1598.                 else if ((i2->Flags & ISMOVL) && (i2->Flags & CHANGED)==0)
  1599.                     i2 = &InstructionTable[ix--];
  1600.             }
  1601.         }
  1602.         in = &InstructionTable[idxInstruction+1];
  1603.         if (!(i1->Name[0] == 'p' && i2->Name[0] == 'p'))
  1604.             goto skip1;
  1605.         if (!(i2->src[0] == '$' && i2->src[1] == '_' && i2->src[2] == '$'))
  1606.             goto skip1;
  1607.         strconstant = FindStringConstant(i2->src+3);
  1608.         len = strlen(strconstant)+1;
  1609.         ChangeInstruction(i2,bb,"movl",i2->src,"%esi");
  1610.  
  1611.         insDst = ChangeInstruction(i1,bb,"movl",i1->src,"%edi");
  1612.  
  1613.         sprintf(tbuf,"$%d",len);
  1614.         insDst = ChangeInstruction(ins,bb,"movl",tbuf,"%ecx");
  1615.         changedInstruction = GetNextChangedInstruction(insDst,bb);
  1616.         insDst->Flags &= ~CHANGED;
  1617.         insDst->Flags |= ADDED;
  1618.         strcpy(changedInstruction->Name,"\trep\n");
  1619.         changedInstruction->src[0] = changedInstruction->dst[0] = 0;
  1620.  
  1621.         if (in->Name[0] == 'a') {
  1622.             insDst = ChangeInstruction(in,bb,"movsb","","");
  1623.         }
  1624.         else strcpy(changedInstruction->src,"movsb\n");
  1625.  
  1626.         FixCalls(ins,bb,idxInstruction);
  1627.         printf("Optimization strcpy\n");
  1628.         return 2;
  1629.     }
  1630. #endif
  1631.     else
  1632.     if (hasRegisterVariables == 0 &&
  1633.         recursion == 0 && !strcmp(savesrc,"_memcpy")) {
  1634.         Instruction *i1,*i2,*i3,*in,*ip;
  1635.         int lab,saveEsi,saveEdi,ismovsw,ismovsd,isExactBytes;
  1636.  
  1637.         ip = NULL;
  1638.         i1 = &InstructionTable[idxInstruction-1];
  1639.         if (i1->Flags & (CHANGED|DELETED)) goto skip1;
  1640.         i2 = &InstructionTable[idxInstruction-2];
  1641.         if (i2->Flags & (CHANGED|DELETED)) goto skip1;
  1642.         i3 = &InstructionTable[idxInstruction-3];
  1643.         if (i3->Flags & (CHANGED|DELETED)) goto skip1;
  1644.         if (idxInstruction > 3)
  1645.             ip = &InstructionTable[idxInstruction-4];
  1646.         in = &InstructionTable[idxInstruction+1];
  1647.         if (in->Flags & (CHANGED|DELETED)) goto skip1;
  1648.         if (i1->Name[0] == 'p' &&
  1649.             i2->Name[0] == 'p' &&
  1650.             i3->Name[0] == 'p' &&
  1651.             in->Name[0] == 'a' &&
  1652.             (!strcmp(in->src,"$12")) &&
  1653.             (i1->Flags & CHANGED) == 0 &&
  1654.             (i2->Flags & CHANGED) == 0 &&
  1655.             (i3->Flags & CHANGED) == 0) {
  1656.             insDst = GetNextChangedInstruction(i3,bb);
  1657.             lab = 0;
  1658.             if (ip && (ip->Flags & CHANGED)== 0 && ip->Flags & ISMOVL &&
  1659.                 ip->dst[0] == '%' &&
  1660.                     (!strcmp(i3->src,ip->src)) &&
  1661.                     (ip->DstReg == ESI || ip->DstReg == EDI)) {
  1662.                     ip->Flags |= DELETED;
  1663.                     deleted++;
  1664.                     strcpy(insDst->Name,"movl");
  1665.                     strcpy(insDst->src,ip->src);
  1666.             }
  1667.             else {
  1668.                 strcpy(insDst->Name,"movl");
  1669.                 strcpy(insDst->src,i3->src);
  1670.             }
  1671.             strcpy(insDst->dst,"%ecx");
  1672.             State[ECX] = Nullst;
  1673.             if (!ediIsSaved ) saveEdi = 1;
  1674.             else if (hasRegisterVariables) saveEdi=1;
  1675.             else saveEdi = IsAliveValue(bb,idxInstruction+2,EDI);
  1676.             if (!esiIsSaved || hasRegisterVariables) saveEsi = 1;
  1677.             else saveEsi = IsAliveValue(bb,idxInstruction+2,ESI);
  1678.             ismovsd = ismovsw = isExactBytes = 0;
  1679.             if (insDst->src[0] == '$' && insDst->src[1] >= '0' &&
  1680.                 insDst->src[1] <= '9') {
  1681.                 int t;
  1682.  
  1683.                 t = atoi(&insDst->src[1]);
  1684.                 if (t > 0) {
  1685.                     if (0 == (t % 4)) {
  1686.                         t /= 4;
  1687.                         ismovsd = 1;
  1688.                     }
  1689.                     else if (0 == (t%2)) {
  1690.                         t /= 2;
  1691.                         ismovsw = 1;
  1692.                     }
  1693.                     if (ismovsd || ismovsw) {
  1694.                         if (t == 1) {
  1695.                             i3->Flags |= DELETED;
  1696.                             i3->Flags &= ~CHANGED;
  1697.                             deleted++;
  1698.                             isExactBytes = 1;
  1699.                         }
  1700.                         else sprintf(insDst->src,"$%d",t);
  1701.                     }
  1702.                 }
  1703.             }
  1704.             if (i3->src[0] != '$') {
  1705.                 changedInstruction = GetNextChangedInstruction(insDst,bb);
  1706.                 insDst->Flags &= ~CHANGED;
  1707.                 insDst->Flags |= ADDED;
  1708.                 lab = genlabel(1);
  1709.                 sprintf(changedInstruction->Name,"\tjecxz");
  1710.                 sprintf(changedInstruction->src,"\t_$%d\n",lab);
  1711.             }
  1712.  
  1713.             insDst = GetNextChangedInstruction(i2,bb);
  1714.             strcpy(insDst->Name,"movl");
  1715.             strcpy(insDst->src,i2->src);
  1716.             if (saveEsi) {
  1717.                 strcpy(insDst->dst,"%edx\n\txchg\t%edx,%esi");
  1718.                 State[EDX] = Nullst;
  1719.             }
  1720.             else {
  1721.                 strcpy(insDst->dst,"%esi");
  1722.                 State[ESI] = Nullst;
  1723.             }
  1724.  
  1725.             insDst = GetNextChangedInstruction(i1,bb);
  1726.             strcpy(insDst->Name,"movl");
  1727.             strcpy(insDst->src,i1->src);
  1728.             if (saveEdi) {
  1729.                 strcpy(insDst->dst,"%eax\n\txchg\t%eax,%edi");
  1730.                 State[EAX] = Nullst;
  1731.             }
  1732.             else {
  1733.                 strcpy(insDst->dst,"%edi");
  1734.                 State[EDI] = Nullst;
  1735.             }
  1736.             if (!isExactBytes) {
  1737.                 insDst = GetNextChangedInstruction(ins,bb);
  1738.                 strcpy(insDst->Name,"rep");
  1739.                 insDst->src[0] = insDst->dst[0] = 0;
  1740.             }
  1741.             else {
  1742.                 ins->Flags |= DELETED;
  1743.                 deleted++;
  1744.             }
  1745.             FixCalls(ins,bb,idxInstruction);
  1746.  
  1747.             insDst = GetNextChangedInstruction(in,bb);
  1748.             if (ismovsw) {
  1749.                 strcpy(insDst->Name,"movsw");
  1750.             }
  1751.             else if (ismovsd) {
  1752.                 strcpy(insDst->Name,"movsl");
  1753.             }
  1754.             else strcpy(insDst->Name,"movsb");
  1755.             if (saveEsi) {
  1756.                 strcat(insDst->Name,"\n");
  1757.                 strcpy(insDst->src,"mov\t%edx,%esi");
  1758.             }
  1759.             if (saveEdi) {
  1760.                 if (!saveEsi) {
  1761.                     strcat(insDst->Name,"\n");
  1762.                     strcpy(insDst->src,"movl\t%eax,%edi");
  1763.                 }
  1764.                 else strcat(insDst->src,"\n\tmov\t%eax,%edi");
  1765.             }
  1766.             if (lab) {
  1767.                 char tlabbuf[30];
  1768.                 sprintf(tlabbuf,"\n_$%d:",lab);
  1769.                 strcat(insDst->src,tlabbuf);
  1770.             }
  1771.             State[ESI] = Nullst;
  1772.             return(2);
  1773.         }
  1774.     }
  1775.  
  1776.     else if (!hasRegisterVariables && !strcmp(savesrc,"_memset")) {
  1777.         Instruction *i1,*i2,*i3,*in,*ip;
  1778.         int ix,isword,isdword,AvoidClobberingEax,AdjustStack;
  1779.  
  1780.         ip = NULL;
  1781.         isword = isdword = 0;
  1782.         ix = idxInstruction-1;
  1783.         i1 = &InstructionTable[ix--];
  1784.         if (i1->Flags & (CHANGED|DELETED)) goto skip1;
  1785.         i2 = &InstructionTable[ix--];
  1786.         if (i2->Flags & (CHANGED|DELETED)) goto skip1;
  1787.         if (i2->Name[0] == 'l' && !strcmp(i2->Name,"leal")) {
  1788.             if ((InstructionTable[ix].Flags & CHANGED) == 0) {
  1789.                 i2 = &InstructionTable[ix--];
  1790.                 if (i2->Name[0] == 'i' && !strcmp(i2->Name,"imul")) {
  1791.                     i2 = &InstructionTable[ix--];
  1792.                 }
  1793.                 else if ((i2->Flags & ISMOVL) && (i2->Flags & CHANGED)==0)
  1794.                     i2 = &InstructionTable[ix--];
  1795.             }
  1796.         }
  1797.         i3 = &InstructionTable[ix--];
  1798.         if (i3->Flags & (CHANGED|DELETED)) goto skip1;
  1799.         if (ix > 0)
  1800.             ip = &InstructionTable[ix--];
  1801.         in = &InstructionTable[idxInstruction+1];
  1802.         if (!strcmp(i1->src,"%eax"))
  1803.             AvoidClobberingEax = 1;
  1804.         else
  1805.             AvoidClobberingEax = 0;
  1806.         if (i1->Name[0] == 'p' &&
  1807.             i2->Name[0] == 'p' &&
  1808.             i3->Name[0] == 'p' &&
  1809.             in->Name[0] == 'a' &&
  1810.             (i1->Flags & CHANGED) == 0 &&
  1811.             (i2->Flags & CHANGED) == 0 &&
  1812.             (i3->Flags & CHANGED) == 0 &&
  1813.             (in->Flags & CHANGED) == 0 &&
  1814.             !(AvoidClobberingEax && !ediIsSaved)) {
  1815.             if (strcmp(in->src,"$12"))
  1816.                 AdjustStack = atoi(&in->src[1]);
  1817.             else
  1818.                 AdjustStack = 0;
  1819.             if (ip && (ip->Flags & ISMOVL) && !strcmp(ip->dst,i3->src)) {
  1820.                 insDst = GetNextChangedInstruction(ip,bb);
  1821.                 strcpy(insDst->Name,ip->Name);
  1822.                 strcpy(insDst->src,ip->src);
  1823.                 i3->Flags |= DELETED;
  1824.                 deleted++;
  1825.             }
  1826.             else {
  1827.                 insDst = GetNextChangedInstruction(i3,bb);
  1828.                 strcpy(insDst->Name,"movl");
  1829.                 if (i3->src[0] == '$' && !strcmp(i2->src,"$0")) {
  1830.                     int val = ReadValue(&i3->src[1]);
  1831.                     if (val) {
  1832.                         if (!(val%4)) {
  1833.                             val = val/4;
  1834.                             isdword = 1;
  1835.                         }
  1836.                         else if (!(val & 1)) {
  1837.                             val = val / 2;
  1838.                             isword = 1;
  1839.                         }
  1840.                         sprintf(insDst->src,"$%d",val);
  1841.                     }
  1842.                     else
  1843.                         strcpy(insDst->src,i3->src);
  1844.                 }
  1845.                 else {
  1846.                     strcpy(insDst->src,i3->src);
  1847.                 }
  1848.             }
  1849.             strcpy(insDst->dst,"%ecx");
  1850.             State[ECX] = Nullst;
  1851.  
  1852.             insDst = GetNextChangedInstruction(i2,bb);
  1853.             if ((!strcmp(i2->src,"$0")) || (!strcmp(i2->src,"$0x0"))) {
  1854.                 strcpy(insDst->Name,"xor");
  1855.                 if (AvoidClobberingEax) {
  1856.                     strcpy(insDst->src,"%edi");
  1857.                 }
  1858.                 else {
  1859.                     strcpy(insDst->src,"%eax");
  1860.                 }
  1861.             }
  1862.             else {
  1863.                 strcpy(insDst->Name,"movl");
  1864.                 strcpy(insDst->src,i2->src);
  1865.             }
  1866.             if (!AvoidClobberingEax) {
  1867.                 strcpy(insDst->dst,"%eax");
  1868.             }
  1869.             else {
  1870.                 strcpy(insDst->dst,"%edi");
  1871.             }
  1872.             State[EAX] = Nullst;
  1873.             if (ediIsSaved == 0 || hasRegisterVariables) {
  1874.                 changedInstruction = GetNextChangedInstruction(insDst,bb);
  1875.                 insDst->Flags |= ADDED;
  1876.                 insDst->Flags &= ~ CHANGED;
  1877.                 strcpy(changedInstruction->Name,"\tpushl");
  1878.                 strcpy(changedInstruction->src,"\t%edi\n");
  1879.                 changedInstruction->dst[0] = 0;
  1880.             }
  1881.  
  1882.             insDst = GetNextChangedInstruction(i1,bb);
  1883.             if (strcmp(i1->src,"%edi")) {
  1884.                 if (!AvoidClobberingEax) {
  1885.                     strcpy(insDst->Name,"movl");
  1886.                     strcpy(insDst->src,i1->src);
  1887.                     strcpy(insDst->dst,"%edi");
  1888.                 }
  1889.                 else {
  1890.                     strcpy(insDst->Name,"xchg");
  1891.                     strcpy(insDst->src,"%eax");
  1892.                     strcpy(insDst->dst,"%edi");
  1893.                 }
  1894.             }
  1895.             else {
  1896.                 i1->Flags |= DELETED;
  1897.                 deleted++;
  1898.             }
  1899.             State[EDI] = Nullst;
  1900.  
  1901.             insDst = GetNextChangedInstruction(ins,bb);
  1902.             strcpy(insDst->Name,"rep");
  1903.             FixCalls(ins,bb,idxInstruction);
  1904.  
  1905.             insDst = GetNextChangedInstruction(in,bb);
  1906.             if (isdword)
  1907.                 strcpy(insDst->Name,"stosl");
  1908.             else if (isword)
  1909.                 strcpy(insDst->Name,"stosw");
  1910.             else strcpy(insDst->Name,"stosb");
  1911.             if (ediIsSaved == 0 || hasRegisterVariables) {
  1912.                 changedInstruction = GetNextChangedInstruction(insDst,bb);
  1913.                 insDst->Flags |= ADDED;
  1914.                 insDst->Flags &= ~ CHANGED;
  1915.                 strcpy(changedInstruction->Name,"\tpopl\t%edi\n");
  1916.                 if (AdjustStack)
  1917.                     sprintf(changedInstruction->dst,"\tadd\t$%d,%%esp\n",AdjustStack-12);
  1918.                 State[EDX] = Nullst;
  1919.             }
  1920.             if (AdjustStack) {
  1921.                 if (ediIsSaved) {
  1922.                     changedInstruction = GetNextChangedInstruction(insDst,bb);
  1923.                     insDst->Flags |= ADDED;
  1924.                     insDst->Flags &= ~ CHANGED;
  1925.                     strcpy(changedInstruction->Name,"\tadd\t");
  1926.                     sprintf(changedInstruction->src,"$%d,",AdjustStack-12);
  1927.                     strcpy(changedInstruction->dst,"%esp\n");
  1928.                 }
  1929.             }
  1930.             Printf1("Optimization 22\n");
  1931.             return(2);
  1932.         }
  1933.     }
  1934. skip1:
  1935.     State[EAX] = State[ECX] = State[EDX] = Nullst;
  1936.     Printf1("eax = ecx = edx = NULL\n");
  1937.     if (State[ESI] && *State[ESI] == '_') State[ESI] = Nullst;
  1938.     if (State[EDI] && *State[EDI] == '_') State[EDI] = Nullst;
  1939.     if (State[EBX] && *State[EBX] == '_') State[EBX] = Nullst;
  1940.     return 0;
  1941. }
  1942.  
  1943. static int FindStateChanges(void)
  1944. {
  1945.     unsigned char *srcCopy;
  1946.     int result;
  1947.  
  1948.     opcode = ins->Name;
  1949.     savesrc = src = ins->src;
  1950.     dst = ins->dst;
  1951.     regdst = regsrc = isImmediate = aReg = 0;
  1952.     result = 1;
  1953.     assert((ins->Flags & TRUNCATED)==0);
  1954.     if (ins->Flags & CHANGED) {
  1955.         src = InstructionTable[ins->ChangedIdx].src;
  1956.         dst = InstructionTable[ins->ChangedIdx].dst;
  1957.     }
  1958.     if (ins->Flags & DELETED) return result;
  1959.     nextIns = &InstructionTable[idxInstruction+1];
  1960.     if (*dst == '%') {
  1961.         dst++;
  1962.         regdst = 1;
  1963.     }
  1964.     if (*src == '%') {
  1965.         src++;
  1966.         regsrc = 1;
  1967.     }
  1968.     else if (*src == '$')
  1969.         isImmediate = 1;
  1970.     isRedundant = 0;
  1971.     isMovl = (ins->Flags & ISMOVL)?1:0;
  1972.     if (dst[0] == '(') {
  1973.         /*
  1974.         replace
  1975.         mov    %esi    (,%edi)
  1976.         mov    (,%edi)    %esi
  1977.         */
  1978.         if ( isMovl && nextIns->src[0] == '(' && !strcmp(src,nextIns->src)) {
  1979.             if (!strcmp(ins->src,nextIns->dst)) {
  1980.                 nextIns->Flags |= DELETED;
  1981.                 Printf1("Optimization 37\n");
  1982.                 deleted++;
  1983.                 result++;
  1984.             }
  1985.             else if (regsrc) {
  1986.                 ChangeInstruction(nextIns,bb,nextIns->Name,ins->src,nextIns->dst);
  1987.             }
  1988.         }
  1989.         return result;
  1990.     }
  1991.     /*
  1992.     replace
  1993.     mov %ecx;%esi
  1994.     mov %esi,%ecx
  1995.     */
  1996.     if (isMovl && regsrc && regdst &&
  1997.         ins->SrcReg < EBP &&
  1998.         (nextIns->Flags &(CHANGED|DELETED)) == 0) {
  1999.  
  2000.         if ((nextIns->Flags & ISMOVL) &&
  2001.             nextIns->src[0] == '%' && nextIns->dst[0] == '%') {
  2002.             if (ins->DstReg == nextIns->SrcReg &&
  2003.                 ins->SrcReg == nextIns->DstReg) {
  2004.                 State[ins->DstReg] = Nullst;
  2005.                 nextIns->Flags |= DELETED;
  2006.                 deleted++;
  2007.                 return 2;
  2008.             }
  2009.         }
  2010.         /*
  2011.         replace
  2012.         movl %esi,%edx
  2013.         leal (%edx,%edi),%edx
  2014.         with
  2015.         leal (%esi,%edi),%edx
  2016.         */
  2017.         if ((nextIns->Flags & ISLEAL) &&
  2018.             (!strcmp(nextIns->dst+1,dst)) &&
  2019.             nextIns->src[0] == '(' &&
  2020.             nextIns->src[1] == '%' &&
  2021.             nextIns->src[5] == ',' &&
  2022.             nextIns->src[6] == '%' &&
  2023.             ( (!strncmp(nextIns->src+2,dst,3)) ||
  2024.               (!strncmp(nextIns->src+7,dst,3)))) {
  2025.             State[ins->DstReg] = Nullst;
  2026. //            printf("%s %s %s\n",nextIns->Name,nextIns->src,nextIns->dst);
  2027.             strcpy(tbuf,nextIns->src);
  2028.             if (!strncmp(nextIns->src+2,dst,3)) {
  2029.                 strncpy(tbuf+2,src,3);
  2030.             }
  2031.             if (!strncmp(nextIns->src+7,dst,3)) {
  2032.                 strncpy(tbuf+7,src,3);
  2033.             }
  2034.             ChangeInstruction(nextIns,bb,nextIns->Name,tbuf,nextIns->dst);
  2035.             ins->Flags |= DELETED;
  2036.             deleted++;
  2037. //            printf("%s %s %s deleted\n",ins->Name,ins->src,ins->dst);
  2038. //            printf("%s %s %s\n\n",nextIns->Name,tbuf,nextIns->dst);
  2039.             return 2;
  2040.         }
  2041.     }
  2042.     if (regdst && isMovl) {
  2043.         if (ins->SrcReg == ins->DstReg) {
  2044.             if (regsrc && !strcmp(src,dst)) {
  2045.                     ins->Flags |= DELETED;
  2046.                     deleted++;
  2047.                     return result;
  2048.             }
  2049.         }
  2050.         /*
  2051.             Try to catch
  2052.                 movl -24(%ebp),%edi
  2053.                 pushl %edi
  2054.  
  2055.                 and replace by
  2056.                 push -24(%ebp)
  2057.         */
  2058.         if (ins->SrcReg == EBP) {
  2059.             if (!hasRegisterVariables &&
  2060.                 nextIns->Name[0] == 'p' && nextIns->Name[1] == 'u' &&
  2061.                 (ins->Flags & SRCDEREFERENCE) == 0 &&
  2062.                 (nextIns->Flags & ISREGSRC) && nextIns->SrcReg == ins->DstReg
  2063.                 && !strcmp(nextIns->src,ins->dst)
  2064.                 && (nextIns->Flags & SRCDEREFERENCE) == 0) {
  2065.                 if (!IsAliveValue(bb,idxInstruction+2,ins->DstReg)) {
  2066.                     ChangeInstruction(ins,bb,"pushl",ins->src,"");
  2067.                     nextIns->Flags |= DELETED;
  2068.                     deleted++;
  2069.                     Printf1("Optimization 23\n");
  2070.                     return(result+1);
  2071.                 }
  2072.             }
  2073.         }
  2074.         if (regsrc &&
  2075.             ins->SrcReg == AX     && ins->DstReg == BX) {
  2076.             /* Try to replace
  2077.                 movl %ax,%bx
  2078.                 movb %bl,-1(%ebp)
  2079.                 with
  2080.                 movl %al,-1(%ebp)
  2081.             */
  2082.  
  2083.             if ((nextIns->Flags & ISGENERICMOVE) && !strcmp(nextIns->src,"%bl")) {
  2084.                 ChangeInstruction(nextIns,bb,nextIns->Name,"%al",nextIns->dst);
  2085.                 ins->Flags |= DELETED;
  2086.                 deleted++;
  2087.                 Printf1("Optimization 24\n");
  2088.                 return(result +1);
  2089.             }
  2090.         }
  2091.         /*
  2092.         replace
  2093.         movl %edx,%esi
  2094.         movl (,%esi),%esi
  2095.         with
  2096.         movl (,%edx),%esi
  2097.         */
  2098.         if (regsrc && nextIns->dst[0] == '%' &&
  2099.             !strcmp(ins->dst,nextIns->dst) &&
  2100.             !strcmp(nextIns->Name,"movl") &&
  2101.             (nextIns->Flags &(CHANGED|DELETED)) == 0 &&
  2102.             ins->src[0] == '%' &&
  2103.             nextIns->SrcReg == ins->DstReg ) {
  2104.             doreplace(nextIns->src,ins->dst+1,ins->src+1,tbuf);
  2105.             ChangeInstruction(nextIns,bb,nextIns->Name,tbuf,nextIns->dst);
  2106.             ins->Flags |= DELETED;
  2107.             deleted++;
  2108.             State[ins->DstReg] = Nullst;
  2109. #if 0
  2110.             printf("move optimization %s %s %s -> %s %s %s [%s %s %s]\n",
  2111.                 ins->Name,ins->src,ins->dst,
  2112.                 nextIns->Name,nextIns->src,nextIns->dst,
  2113.                 pins->Name,pins->src,pins->dst
  2114.                 );
  2115. #endif
  2116.             return 2;
  2117.         }
  2118.         if (!regsrc && !isImmediate) {
  2119.             if (State[EAX] && !strcmp(src,State[EAX])) {
  2120.                 Printf2("%s was in eax\n",State[EAX]);
  2121.                 if (ins->DstReg == EAX) {
  2122.                     ins->Flags |= DELETED;
  2123.                     deleted++;
  2124.                 }
  2125.                 else {
  2126.                     redundant++;
  2127.                     isRedundant = EAX;
  2128.                 }
  2129.             }
  2130.             if (State[EBX] && !strcmp(src,State[EBX])) {
  2131.                 Printf2("%s was in ebx\n",State[EBX]);
  2132.                 if (ins->DstReg == EBX) {
  2133.                     ins->Flags |= DELETED;
  2134.                     deleted++;
  2135.                 }
  2136.                 else {
  2137.                     redundant++;
  2138.                     isRedundant = EBX;
  2139.                 }
  2140.             }
  2141.             if (State[ECX] && !strcmp(src,State[ECX])) {
  2142.                 Printf2("%s was in ecx\n",State[ECX]);
  2143.                 if (ins->DstReg == ECX) {
  2144.                     ins->Flags |= DELETED;
  2145.                     deleted++;
  2146.                 }
  2147.                 else {
  2148.                     redundant++;
  2149.                     isRedundant = ECX;
  2150.                 }
  2151.             }
  2152.             if (State[EDX] && !strcmp(src,State[EDX])) {
  2153.                 Printf2("%s was in edx\n",State[EDX]);
  2154.                 if (ins->DstReg == EDX) {
  2155.                     ins->Flags |= DELETED;
  2156.                     deleted++;
  2157.                 }
  2158.                 else {
  2159.                     redundant++;
  2160.                     isRedundant = EDX;
  2161.                 }
  2162.             }
  2163.             if (State[ESI] && !strcmp(src,State[ESI])) {
  2164.                 Printf2("%s was in esi\n",State[ESI]);
  2165.                 if (ins->DstReg == ESI) {
  2166.                     ins->Flags |= DELETED;
  2167.                     deleted++;
  2168.                 }
  2169.                 else {
  2170.                     redundant++;
  2171.                     isRedundant = ESI;
  2172.                 }
  2173.             }
  2174.             if (State[EDI] && !strcmp(src,State[EDI])) {
  2175.                 Printf2("%s was in edi\n",State[EDI]);
  2176.                 if (ins->DstReg == EDI) {
  2177.                     ins->Flags |= DELETED;
  2178.                     deleted++;
  2179.                 }
  2180.                 else {
  2181.                     redundant++;
  2182.                     isRedundant = EDI;
  2183.                 }
  2184.             }
  2185.             if (isRedundant && /*!hasRegisterVariables &&*/
  2186.                 src[0] != '$' && (ins->Flags & (CHANGED|DELETED)) == 0) {
  2187.                 ChangeRedundantLoad(ins,isRedundant,bb,idxInstruction,1/*!hasRegisterVariables*/);
  2188.             }
  2189.         }
  2190.         if (ins->Flags & DELETED)
  2191.             return(result);
  2192.     }
  2193.     if (ins->DstReg > ESP) {
  2194.         if (ins->DstReg < SP+1) State[ins->DstReg-ESP] = Nullst;
  2195.         else if ((ins->Flags & ISGENERICMOVE) == 0) {
  2196.             int r;
  2197.  
  2198.             r = ins->DstReg & 0xFF;
  2199.             if (r < ESP) {
  2200.                 State[r] = Nullst;
  2201.                 Printf2("%s = NULL\n",RegisterNames[r]);
  2202.             }
  2203.             r = (ins->DstReg >> 8) & 0xFF;
  2204.             if (r < ESP) {
  2205.                 State[r] = Nullst;
  2206.                 Printf2("%s = NULL\n",RegisterNames[r]);
  2207.             }
  2208.         }
  2209.     }
  2210.     if (isMovl &&
  2211.         regsrc &&
  2212.         regdst &&
  2213. //        !hasRegisterVariables &&
  2214.         isImmediate == 0 &&
  2215.         (ins->Flags&CHANGED) == 0 &&
  2216.         ins->SrcReg < EBP &&
  2217.         ins->DstReg < EBP) {
  2218.         int i = RegToRegCopy();
  2219.         if (i) return i;
  2220.     }
  2221.     /*
  2222.     This should have taken into account the fact that after an
  2223.     orl    %eax,%eax
  2224.     jne _$label
  2225.     %eax is zero. Then any 'xor %eax,%eax' after this can be deleted
  2226.     The results are disappointing. 210 bytes gained from 543188...
  2227.     */
  2228.     if (isMovl == 0 && regsrc && regdst
  2229.         && ins->SrcReg == ins->DstReg
  2230.         && opcode[0] == 'o' && opcode[1] == 'r'
  2231.         && (opcode[2] == 0 || opcode[2] == 'l')
  2232.         && ins->SrcReg < EBP) {
  2233.         if ((nextIns->Flags & (CHANGED|DELETED)) == 0
  2234.             && !strcmp(nextIns->Name,"jne")) {
  2235.             Instruction *tmpins = nextIns;
  2236.             nextIns++;
  2237.             if ((nextIns->Flags & (CHANGED|DELETED)) == 0) {
  2238.                 if (nextIns->SrcReg == ins->SrcReg &&
  2239.                     nextIns->DstReg == ins->SrcReg &&
  2240.                     nextIns->src[0] == '%' &&
  2241.                     nextIns->dst[0] == '%' &&
  2242.                     !strcmp(nextIns->Name,"xor")) {
  2243.                     nextIns++;
  2244.                     if (strcmp(nextIns->Name,"jmp")) {
  2245.                         nextIns--;
  2246.                         nextIns->Flags |= DELETED;
  2247.                         deleted++;
  2248.                         Printf1("Optimization 47\n");
  2249.                     }
  2250.                     else {
  2251.                         // This is ridiculous. Changed from
  2252.                         // 542968 to 542924: 44 bytes saved only!
  2253.                         // should be faster though, since a jump is saved
  2254.                         if (!strncmp(nextIns->End,tmpins->src,strlen(tmpins->src))
  2255.                             && ins->SrcReg == EAX) {
  2256.                             int lab = atoi(nextIns->src+2);
  2257.                             if (lab == lastLabel) {
  2258.                                 ChangeInstruction(tmpins,bb,"je",nextIns->src,"");
  2259.                                 nextIns--;
  2260.                                 nextIns->Flags |= DELETED;
  2261.                                 deleted++;
  2262.                                 nextIns++;
  2263.                                 nextIns->Flags |= DELETED;
  2264.                                 deleted++;
  2265.                                 return(4);
  2266.                             }
  2267.                         }
  2268.                     }
  2269.                 }
  2270.                 else if (nextIns->src[0] == '$' &&
  2271.                     nextIns->src[1] == '0' &&
  2272.                     nextIns->src[2] == 0 &&
  2273.                     (!strcmp(nextIns->Name,"movl") || (nextIns->Flags & ISCOMPARE))) {
  2274.                     ChangeInstruction(nextIns,bb,nextIns->Name,ins->src,nextIns->dst);
  2275.                     Printf1("Optimization 47\n");
  2276.                     return(3);
  2277.                 }
  2278.             }
  2279.         }
  2280.         return(result);
  2281.     }
  2282.     if ((isMovl == 0) && (ins->Flags & ISCOMPARE)) {
  2283.         return compare();
  2284.     }
  2285.  
  2286.     if ((ins->Flags & ISGENERICMOVE) == 0) {
  2287.         /* delete additions and substractions of zero */
  2288.         if ((ins->Flags & (CHANGED|DELETED))==0 &&
  2289.             (opcode[0] == 'a' && opcode[1] == 'd' && opcode[2] == 'd') ||
  2290.             (opcode[0] == 's' && opcode[1] == 'u' && opcode[2] == 'b')) {
  2291.             if (isImmediate && src[1] == '0') {
  2292.                 if (src[2] == 0 || (src[2] == 'x' && src[3] == '0' && src[4] == 0)) {
  2293.                     ins->Flags |= DELETED;
  2294.                     return result;
  2295.                 }
  2296.             }
  2297.             lastIns = GetLastInstruction(idxInstruction);
  2298.             /*
  2299.                 Replace
  2300.                 addl    $-1,reg
  2301.                 by
  2302.                 inc        reg
  2303.             */
  2304.             if (((ins->Flags & CHANGED) == 0) && isImmediate && src[1] == '-'
  2305.                 && src[2] == '1' && src[3] == 0) {
  2306.                 unsigned char *op;
  2307.                 if (regdst) {
  2308.                     tbuf[0] = '%';
  2309.                     strcpy(tbuf+1,dst);
  2310.                 }
  2311.                 else strcpy(tbuf,dst);
  2312.                 if (*opcode == 'a')
  2313.                     op = "decl";
  2314.                 else
  2315.                     op = "incl";
  2316.                 if (*dst != '%') doclobber(dst,10000);
  2317.                 ChangeInstruction(ins,bb,op,tbuf,"");
  2318.                 Printf1("addl/subl->inc/dec\n");
  2319.             }
  2320.             else
  2321.             /*
  2322.                 Replace postincrement from
  2323.                     mov mem,reg1    load value
  2324.                     mov reg1,reg2    save old value in reg2
  2325.                     inc reg1        add offset
  2326.                     mov reg1,mem    store updated value
  2327.  
  2328.                     to
  2329.  
  2330.                     mov    mem,reg1    load value
  2331.                     inc reg1        add offset
  2332.                     xchg reg1,mem    store new value AND reload old
  2333.             */
  2334.             if ((ins->Flags & CHANGED) == 0 && recursion == 0 &&
  2335.                 (ins->Flags & ISREGDST) &&
  2336. //                !hasRegisterVariables &&
  2337.                 isImmediate && idxInstruction >1) {
  2338.                 if ((lastIns->Flags & ISREGSRC) && (lastIns->Flags & ISREGDST)
  2339.                     && (lastIns->Flags & ISMOVL) &&
  2340.                     lastIns->DstReg == ins->DstReg &&
  2341.                     !IsAliveValue(bb,idxInstruction+2,ins->DstReg)) {
  2342.                     Instruction *tmp;
  2343.  
  2344.                     tmp = lastIns - 1;
  2345.                     if (((tmp->Flags & CHANGED)==0) &&
  2346.                         (tmp->Flags & ISMOVL) &&
  2347.                         (tmp->Flags & ISREGSRC) == 0 &&
  2348.                         tmp->DstReg == lastIns->SrcReg) {
  2349.  
  2350.                         if ((nextIns->Flags & ISREGSRC) && !strcmp(tmp->src,nextIns->dst)) {
  2351.                             unsigned char *srcC;
  2352.                             if (lastIns->Flags & CHANGED) {
  2353.                                 srcC = InstructionTable[lastIns->ChangedIdx].src;
  2354.                             }
  2355.                             else
  2356.                                 srcC = lastIns->src;
  2357.                             lastIns->Flags |= DELETED;
  2358.                             deleted++;
  2359.                             tmp->Flags &= ~DELETED;
  2360.                             if (opcode[0] == 's') {
  2361.                                 sprintf(tbuf,"$-%s",src+1);
  2362.                             }
  2363.                             else strcpy(tbuf,src);
  2364.                             ChangeInstruction(tmp,bb,"movl",nextIns->dst,srcC);
  2365.                             insDst = ChangeInstruction(ins,bb,"add",tbuf,nextIns->dst);
  2366.                             nextIns->Flags |= DELETED;
  2367.                             deleted++;
  2368.                             doclobber(insDst->src,10000);
  2369.                             if (lastIns->SrcReg < ESP)
  2370.                                 State[lastIns->SrcReg] = Nullst;
  2371.                             Printf3("%s = %s = NULL\n",RegisterNames[lastIns->SrcReg],
  2372.                                 RegisterNames[lastIns->DstReg]);
  2373.                             Printf1("Optimization 13 (postincrement)\n");
  2374.                             return(result+1);
  2375.                         }
  2376.                     }
  2377.                     else if ((lastIns->Flags & CHANGED) == 0 &&
  2378.                         !hasRegisterVariables) {
  2379.                         unsigned char *minus;
  2380.  
  2381.                         if (opcode[0] == 's') minus = "-";
  2382.                         else minus = "";
  2383.                         sprintf(tbuf,"%s%s(%s)",minus,ins->src+1,lastIns->src);
  2384.                         ChangeInstruction(ins,bb,"leal",tbuf,ins->dst);
  2385.                         lastIns->Flags |= DELETED;
  2386.                         deleted++;
  2387.                         if (ins->DstReg < ESP)
  2388.                             State[ins->DstReg] = Nullst;
  2389.                         Printf1("Optimization 16\n");
  2390.                         return result;
  2391.                     }
  2392.                 }
  2393.             }
  2394.             if (((ins->Flags & CHANGED) == 0) && isImmediate && src[1] == '1'
  2395.                 && src[2] == 0) {
  2396.                 unsigned char *op;
  2397.                 if (regdst) {
  2398.                     tbuf[0] = '%';
  2399.                     strcpy(tbuf+1,dst);
  2400.                 }
  2401.                 else strcpy(tbuf,dst);
  2402.                 if (*opcode == 'a')
  2403.                     op = "incl";
  2404.                 else
  2405.                     op = "decl";
  2406.                 if (*dst != '%') doclobber(dst,10000);
  2407.                 ChangeInstruction(ins,bb,op,tbuf,"");
  2408.                 Printf1("addl/subl->inc/dec\n");
  2409.             }
  2410.             if (((ins->Flags & CHANGED) == 0) &&
  2411.                 ! hasRegisterVariables &&
  2412.                 isImmediate && regdst && idxInstruction > 0) {
  2413.                 if (!strcmp(lastIns->Name,"movl") &&
  2414.                     lastIns->dst[0] == '%' &&
  2415.                     lastIns->SrcReg < EBP &&
  2416.                     !strcmp(lastIns->src,nextIns->dst) &&
  2417.                     !strcmp(lastIns->dst,ins->dst) &&
  2418.                     !strcmp(ins->dst,nextIns->src) &&
  2419.                     !IsAliveValue(bb,idxInstruction+2,ins->DstReg) ) {
  2420.                     /* replace
  2421.                     movl _var,%edi
  2422.                     addl $8,%edi
  2423.                     movl %edi,_var
  2424.                     with
  2425.                     addl $8,_var
  2426.                     */
  2427.                     ChangeInstruction(ins,bb,ins->Name,ins->src,lastIns->src);
  2428.                     lastIns->Flags |= DELETED;
  2429.                     State[ins->DstReg] = Nullst;
  2430.                     nextIns->Flags |= DELETED;
  2431.                     Printf1("Optimization 42\n");
  2432.                     deleted += 2;
  2433.                     return(2);
  2434.                 }
  2435.             }
  2436.         }
  2437.         if (isImmediate &&
  2438.             (ins->Flags & (CHANGED|DELETED)) == 0 &&
  2439.             opcode[0] == 't' && opcode[1] == 'e' &&
  2440.             opcode[2] == 's' && opcode[3] == 't') {
  2441.             int val;
  2442.  
  2443.             val = CheckValueAlreadyLoaded(ins->dst);
  2444.             if (val) {
  2445.                 sprintf(tbuf,"%%%s",RegisterNames[val]);
  2446.                 ChangeInstruction(ins,bb,ins->Name,ins->src,tbuf);
  2447.                 Printf1("Optimization 44.5\n");
  2448.                 return 1;
  2449.             }
  2450.             if (opcode[4] == 'l') {
  2451.                 unsigned char * pval = ins->src;
  2452.                 unsigned char *dst = ins->dst;
  2453.                 char suffix=0;
  2454.  
  2455.                 if (*pval == '$') pval++;
  2456.                 if (*pval == '0' && pval[1] == 'x') {
  2457.                     val = strtoul(pval+2,(char **)&pval,16);
  2458.                 }
  2459.                 else val = strtoul(pval,(char **)&pval,10);
  2460.                 if (val > 0) {
  2461.                     if (val < 128) {
  2462.                         if (regdst &&
  2463.                             (ins->DstReg == ESI || ins->DstReg == EDI)) {
  2464.                             if (ins->DstReg == ESI)
  2465.                                 dst = "%si";
  2466.                             else
  2467.                                 dst = "%di";
  2468.                             suffix = 'w';
  2469.                         }
  2470.                         else {
  2471.                             suffix = 'b';
  2472.                             if (regdst) {
  2473.                                 if (ins->DstReg == EAX)
  2474.                                     dst = "%al";
  2475.                                 if (ins->DstReg == EBX)
  2476.                                     dst = "%bl";
  2477.                                 if (ins->DstReg == ECX)
  2478.                                     dst = "%cl";
  2479.                                 if (ins->DstReg == EDX)
  2480.                                     dst = "%dl";
  2481.                             }
  2482.                         }
  2483.                     }
  2484.                     else if (val < 65535) {
  2485.                         suffix = 'w';
  2486.                         if (regdst) {
  2487.                             if (ins->DstReg == EAX)
  2488.                                 dst = "%ax";
  2489.                             if (ins->DstReg == EBX)
  2490.                                 dst = "%bx";
  2491.                             if (ins->DstReg == ECX)
  2492.                                 dst = "%cx";
  2493.                             if (ins->DstReg == EDX)
  2494.                                 dst = "%dx";
  2495.                             if (ins->DstReg == ESI)
  2496.                                 dst = "%si";
  2497.                             if (ins->DstReg == EDI)
  2498.                                 dst = "%di";
  2499.                         }
  2500.                     }
  2501.                     if (suffix) {
  2502.                         sprintf(tbuf,"test%c",suffix);
  2503.                         ChangeInstruction(ins,bb,tbuf,ins->src,dst);
  2504.                         return(result);
  2505.                     }
  2506.                 }
  2507.             }
  2508.         }
  2509.         if ((opcode[0] == 'd' && opcode[1] == 'i' && opcode[2] == 'v') ||
  2510.             (opcode[0] == 'i' && opcode[1] == 'm' && opcode[2] == 'u') ||
  2511.             (opcode[0] == 'i' && opcode[1] == 'd' && opcode[2] == 'i') ||
  2512.             (opcode[0] == 'm' && opcode[1] == 'u' && opcode[2] == 'l')) {
  2513.             Printf1("div/mul: eax = edx = NULL\n");
  2514.             State[EAX] = State[EDX] = Nullst;
  2515.         }
  2516.         /*
  2517.         Try to replace a sequence of instructions like
  2518.         xor        %eax,%eax
  2519.         movl    %eax,memory1
  2520.         xor        %eax,%eax
  2521.         movl    %eax,memory2
  2522.         with
  2523.         xor        %eax,%eax
  2524.         movl    %eax,memory1
  2525.         movl    %eax,memory2
  2526.         */
  2527.         if ((ins->Flags & CHANGED) == 0 &&
  2528.             opcode[0] == 'x' && opcode[1] == 'o' && opcode[2] == 'r') {
  2529.             if (ins->SrcReg == ins->DstReg && ins->SrcReg == EAX) {
  2530.                 Instruction *ins1,*ins2;
  2531.                 int idx = idxInstruction+1;
  2532.  
  2533.                 for ( ; ;) {
  2534.                     if (idx >= bb->NrOfInstructions) break;
  2535.                     ins1 = &InstructionTable[idx];
  2536.                     ins2 = &InstructionTable[idx+1];
  2537.                     if (ins1->Flags & CHANGED) break;
  2538.                     if (ins2->Flags & CHANGED) break;
  2539.                     if ((ins1->Flags & ISGENERICMOVE) &&
  2540.                         ins1->SrcReg == EAX &&
  2541.                         ins1->src[0] == '%' &&
  2542.                         ins2->Name[0] == 'x' && ins2->Name[1] == 'o' &&
  2543.                         ins2->SrcReg == ins2->DstReg &&
  2544.                         ins2->SrcReg == EAX &&
  2545.                         ins2->src[0] == '%' && ins2->dst[0] == '%' &&
  2546.                         ins2->src[2] == 'a' && ins2->dst[2] == 'a') {
  2547.                         ins2->Flags |= DELETED;
  2548.                         deleted++;
  2549.                         Printf1("Optimization 31\n");
  2550.                     }
  2551.                     else if (
  2552.                         (ins1->Flags & ISGENERICMOVE) &&
  2553.                         ins1->SrcReg == EAX &&
  2554.                         ins1->src[0] == '%' &&
  2555.                         (ins2->Flags & ISGENERICMOVE) &&
  2556.                         (!strcmp(ins2->src,"$0") || !strcmp(ins2->src,"$0x0")) &&
  2557.                         (!strcmp(ins2->Name,"movl") || !strcmp(ins2->Name,"movw"))) {
  2558.                         if (ins2->Name[3] == 'l')
  2559.                             strcpy(tbuf,"%eax");
  2560.                         else
  2561.                             strcpy(tbuf,"%ax");
  2562.                         ChangeInstruction(ins2,bb,ins2->Name,tbuf,ins2->dst);
  2563.                         Printf1("Optimization 32\n");
  2564.                         idx += 2;
  2565.                         continue;
  2566.                     }
  2567.                     else break;
  2568.                     idx += 2;
  2569.                 }
  2570.             }
  2571.         }
  2572.         if ((opcode[0] == 'i' && opcode[1] == 'n' && opcode[2] == 'c') ||
  2573.             (opcode[0] == 'd' && opcode[1] == 'e' && opcode[2] == 'c')) {
  2574.                 doclobber(savesrc,10000);
  2575.         }
  2576.         /* all arithmetic instructions are discarded */
  2577.         if (regsrc) {
  2578.             if (ins->SrcReg < ESP && State[ins->SrcReg]) {
  2579.                 doclobber(State[ins->SrcReg],10000);
  2580.                 State[ins->SrcReg] = Nullst;
  2581.             }
  2582.         }
  2583.         if (regdst) {
  2584.             if (ins->DstReg < ESP && State[ins->DstReg]) {
  2585.                 doclobber(State[ins->DstReg],10000);
  2586.                 State[ins->DstReg] = Nullst;
  2587.             }
  2588.         }
  2589.         doclobber(ins->dst,10000);
  2590.         if (opcode[0] == 'f') {
  2591.             if (opcode[1] == 's' && opcode[2] == 't'
  2592.                 && opcode[3] == 's') {
  2593.                 State[EAX] = Nullst;
  2594.             }
  2595.             if (!strcmp(opcode,"fstpl")) {
  2596.                 if (!strcmp(nextIns->Name,"fldl") &&
  2597.                     !strcmp(nextIns->src,ins->src)) {
  2598.                     nextIns->Flags |= DELETED;
  2599.                     deleted++;
  2600.                     ChangeInstruction(ins,bb,"fstl",ins->src,"");
  2601.                     return(2);
  2602.                 }
  2603.             }
  2604.         }
  2605.         src = Nullst;
  2606.     }
  2607.     old = Nullst;
  2608.     if ((isMovl == 0) && !strcmp("rep",opcode)) {
  2609.         Instruction *loadEcxIns;
  2610.         int i;
  2611.  
  2612.         Printf1("rep movsb: esi = edi = ecx = NULL\n");
  2613.         State[ESI] = State[EDI] = State[ECX] = Nullst;
  2614.         if (idxInstruction > 0 && nextIns->Name[4] == 'b' && nextIns->Name[0] == 'm') {
  2615.             i = idxInstruction-1;
  2616.             loadEcxIns = &InstructionTable[i];
  2617.             while (i >= 0) {
  2618.                 if (loadEcxIns->DstReg == ECX) {
  2619.                     if (loadEcxIns->src[0] == '$') break;
  2620.                     else return result;
  2621.                 }
  2622.                 i--;
  2623.                 loadEcxIns--;
  2624.             }
  2625.             /*
  2626.                 replace in the block move instructions the
  2627.                 movsb construct by movsw (100% faster) or the
  2628.                 movsd (400% faster).
  2629.             */
  2630.             if (i > 1) {
  2631.                 int quantity;
  2632.  
  2633.                 quantity = atoi(loadEcxIns->src + 1);
  2634.                 if (quantity > 0) {
  2635.                     char tbuf[10];
  2636.                     int changed = 0;
  2637.  
  2638.                     if (0 == (quantity % 4)) {
  2639.                         quantity = quantity/4;
  2640.                         changed = 'l';
  2641.                     }
  2642.                     else if (0 == (quantity % 2)) {
  2643.                         quantity = quantity/2;
  2644.                         changed = 'w';
  2645.                     }
  2646.                     if (changed) {
  2647.                         sprintf(tbuf,"$%d",quantity);
  2648.                         ChangeInstruction(loadEcxIns,bb,loadEcxIns->Name,tbuf,loadEcxIns->dst);
  2649.  
  2650.                         sprintf(tbuf,"movs%c",changed);
  2651.                         ChangeInstruction(nextIns,bb,tbuf,"","");
  2652.                         Printf1("movsb->movsd\n");
  2653.                     }
  2654.                 }
  2655.             }
  2656.         }
  2657.         return result;
  2658.     }
  2659.     if (opcode[0] == 'm' && opcode[1] == 'o' && opcode[2] == 'v'
  2660.         && opcode[3] == 's' && opcode[5] == 0
  2661.         && (opcode[4] == 'l' || opcode[4] == 'w' || opcode[4] == 'b')) {
  2662.         Printf1("rep movsb: esi = edi = ecx = NULL\n");
  2663.         State[ESI] = State[EDI] = State[ECX] = Nullst;
  2664.         return 1;
  2665.     }
  2666.     /*
  2667.     Test if the source of a push instruction is already in a register
  2668.     */
  2669.     if ((ins->Flags & CHANGED) == 0 && !isImmediate &&
  2670.         !regsrc && opcode[0] == 'p' && opcode[1] == 'u'
  2671.         && opcode[2] == 's') {
  2672.         int ir;
  2673.         for (ir = EAX; ir<EBP;ir++) {
  2674.             if (State[ir] &&
  2675.               State[ir][0] != '%' &&
  2676.              !strcmp(ins->src,State[ir])) {
  2677.                 char tmpbuf[10];
  2678.  
  2679.                 sprintf(tmpbuf,"%%%s",RegisterNames[ir]);
  2680.                 ChangeInstruction(ins,bb,opcode,tmpbuf,"");
  2681.                 Printf1("Optimization 37\n");
  2682.                 return(result);
  2683.             }
  2684.         }
  2685.     }
  2686.     if (regdst) {
  2687.         if (ins->Flags & SRCDEREFERENCE) src = Nullst;
  2688.         else if ((ins->Flags & SRCOFFSET) && ins->SrcReg != EBP){
  2689.                 src = Nullst;
  2690.         }
  2691.         else if (!isMovl) src = Nullst;
  2692.         aReg = ins->DstReg;
  2693.         if (aReg < EBP && aReg > 0) {
  2694.             old = State[aReg];
  2695.             if ((ins->Flags & CHANGED) == 0 &&
  2696.                 old &&
  2697.                 old != Nullst &&
  2698.                 ins->SrcReg < ESP &&
  2699. //                ! hasRegisterVariables &&
  2700.                 (isMovl || (!strcmp(ins->Name,"movsbl") || !strcmp(ins->Name,"movswl")))) {
  2701.                 if (isUsedInBlock(1+idxInstruction,old,bb,aReg)) {
  2702.                     int r = AvoidClobber(RegisterNames[aReg],idxInstruction,bb);
  2703.  
  2704.                     if (r) {
  2705.                         Printf2("avoiding clobbering of %s\n",RegisterNames[aReg]);
  2706.                         aReg = r;
  2707.                         old = Nullst;
  2708.                     }
  2709.                     else ins->Flags |= CLOBBERS;
  2710.                 }
  2711.                 else ins->Flags |= CLOBBERS;
  2712.             }
  2713.             else ins->Flags |= CLOBBERS;
  2714.             if (regsrc) src = Nullst;
  2715.             State[aReg] = src;
  2716.             Printf3("%s = %s\n",RegisterNames[aReg],src);
  2717.             bb->Registers[aReg] = 1;
  2718.             if (ins->Flags & CHANGED) return(result);
  2719.         }
  2720.         if (((ins->Flags & CHANGED) == 0) && isMovl && isImmediate) {
  2721.             if (savesrc[1] == '0' && savesrc[2] == 0) {
  2722.                 /*
  2723.                 Replace
  2724.                     movl $0,%eax
  2725.                 with
  2726.                     xor %eax,%eax
  2727.                 */
  2728.                 ChangeInstruction(ins,bb,"xor",ins->dst,ins->dst);
  2729.                 Printf1("xor added\n");
  2730.                 if (ins->DstReg < ESP) State[ins->DstReg] = "$0";
  2731.                 return(result);
  2732.             }
  2733.             if (savesrc[1] == '1' && savesrc[2] == 0) {
  2734.                 changedInstruction = ChangeInstruction(ins,bb,"xor",ins->dst,ins->dst);
  2735.                 changedInstruction->Flags &= ~CHANGED;
  2736.                 changedInstruction->Flags |= ADDED;
  2737.                 changedInstruction = GetNextChangedInstruction(changedInstruction,bb);
  2738.                 sprintf(tbuf,"\tinc\t%s\n",ins->dst);
  2739.                 strcpy(changedInstruction->Name,tbuf);
  2740.                 if (ins->DstReg < ESP) State[ins->DstReg] = "$1";
  2741.                 return(result);
  2742.             }
  2743.  
  2744.         }
  2745.         if (regsrc && ins->DstReg == EAX && idxInstruction > 2
  2746.             && idxInstruction >= bb->NrOfInstructions-2
  2747.             && isMovl
  2748.             && !hasRegisterVariables
  2749.             && ((InstructionTable[idxInstruction+1].Name[0] == 'j') ||
  2750.                 (idxInstruction == bb->NrOfInstructions-1))) {
  2751.             lastIns = GetLastInstruction(idxInstruction);
  2752.  
  2753.             if (lastIns &&
  2754.                 (lastIns->Flags & ISMOVL)
  2755.                 && lastIns->DstReg == ins->SrcReg
  2756.                 && lastIns->DstReg < ESP
  2757.                 && ins->SrcReg < ESP
  2758.                 && lastIns->dst[0] == '%') {
  2759.                 lastIns->Flags |= DELETED;
  2760.                 if (lastIns->Flags & CHANGED) {
  2761.                     changedInstruction = &InstructionTable[lastIns->ChangedIdx];
  2762.                     srcCopy = changedInstruction->src;
  2763.                     lastIns->Flags &= ~CHANGED;
  2764.                 }
  2765.                 else {
  2766.                     srcCopy = lastIns->src;
  2767.                 }
  2768.                 deleted++;
  2769.                 ChangeInstruction(ins,bb,opcode,srcCopy,ins->dst);
  2770.                 Printf1("Redundant move\n");
  2771.             }
  2772.         }
  2773.         /* replace
  2774.             mov %edi %esi
  2775.             mov %esi -4(%ebp)
  2776.             with
  2777.             mov %edi, -4(%ebp)
  2778.             P.S. This is not worth the effort: 517476 to 517456
  2779.             */
  2780.         if (regsrc &&
  2781.             !hasRegisterVariables &&
  2782.             isMovl &&
  2783.             idxInstruction < (bb->NrOfInstructions-1)
  2784.             && aReg < EBP && ins->SrcReg < EBP
  2785.             && (ins->Flags & CHANGED)==0) {
  2786.  
  2787.             if ((nextIns->Flags & ISMOVL) && (nextIns->Flags & CHANGED)==0
  2788.                 && (ins->DstReg == EDI || ins->DstReg == ESI)
  2789.                 && (nextIns->Flags & ISREGSRC) && nextIns->SrcReg == ins->DstReg
  2790.                 /*&& (nextIns->Flags & ISREGDST) == 0*/ && (nextIns->SrcReg != nextIns->DstReg)
  2791.                 && (nextIns->DstReg < ESP)) {
  2792.                 if (!IsAliveValue(bb,idxInstruction+2,ins->DstReg)) {
  2793.                     ins->Flags |= DELETED;
  2794.                     ChangeInstruction(nextIns,bb,nextIns->Name,ins->src,nextIns->dst);
  2795.                     deleted++;
  2796.                     Printf1("Optimization 28\n");
  2797.                     return(result);
  2798.                 }
  2799.             }
  2800.         }
  2801.         /* replace
  2802.             mov -4(%ebp),%esi
  2803.             mov %esi %edi
  2804.             with
  2805.             mov  -4(%ebp),%edi
  2806.             */
  2807.         if (regsrc &&
  2808.             !hasRegisterVariables &&
  2809.             isMovl &&
  2810.             idxInstruction > 0
  2811.             && aReg < EBP && ins->SrcReg < EBP
  2812.             && (ins->Flags & CHANGED)==0) {
  2813.             lastIns = &InstructionTable[idxInstruction-1];
  2814.  
  2815.             if ((lastIns->Flags & ISMOVL) && (lastIns->Flags & (CHANGED|DELETED))==0
  2816.                 && (ins->SrcReg == EDI || ins->SrcReg == ESI)
  2817.                 && (lastIns->Flags & ISREGDST) && lastIns->DstReg == ins->SrcReg
  2818.                 && (lastIns->Flags & ISREGSRC) == 0 && (lastIns->SrcReg != lastIns->DstReg)
  2819.                 && (lastIns->DstReg < ESP)) {
  2820.                 if (!IsAliveValue(bb,idxInstruction+1,ins->SrcReg)) {
  2821.                     ins->Flags |= DELETED;
  2822.                     ChangeInstruction(lastIns,bb,lastIns->Name,lastIns->src,ins->dst);
  2823.                     deleted++;
  2824.                     State[lastIns->DstReg] = Nullst;
  2825.                     Printf1("Optimization 29\n");
  2826.                     return(result);
  2827.                 }
  2828.             }
  2829.         }
  2830.         if ((ins->Flags & CHANGED) == 0 &&
  2831.             regdst &&
  2832.             !hasRegisterVariables &&
  2833.             regsrc && isMovl && aReg == EDI && ins->SrcReg == EAX) {
  2834.             int notAlive;
  2835.             /*
  2836.             replace
  2837.             movl    %eax,%edi
  2838.             or        %edi,%edi
  2839.             with
  2840.             or    %eax,%eax
  2841.             */
  2842.             notAlive = !IsAliveValue(bb,idxInstruction+2,EDI);
  2843.             if (nextIns->Flags & CHANGED) notAlive = 0;
  2844.             if ((notAlive) &&
  2845.                 (!strcmp(nextIns->src,nextIns->dst)) &&
  2846.                 (!strcmp(nextIns->src,"%edi")) &&
  2847.                 (nextIns->Name[0] == 'o' && nextIns->Name[1] == 'r')) {
  2848.                 ins->Flags |= DELETED;
  2849.                 ChangeInstruction(nextIns,bb,nextIns->Name,"%eax","%eax");
  2850.                 ins->Flags |= DELETED;
  2851.                 deleted++;
  2852.                 Printf1("Optimization 33\n");
  2853.                 return(result+1);
  2854.             }
  2855.             /*
  2856.             replace
  2857.             movl    %eax,%edi
  2858.             movl    %edi,memory reference
  2859.             */
  2860.             else
  2861.                 if ((notAlive) && !hasRegisterVariables &&
  2862.                     (nextIns->Flags & ISMOVL) &&
  2863.                     (nextIns->SrcReg == EDI) &&
  2864.                     (nextIns->src[0] == '%')) {
  2865.                     ChangeInstruction(nextIns,bb,nextIns->Name,"%eax",nextIns->dst);
  2866.                     ins->Flags |= DELETED;
  2867.                     deleted++;
  2868.                     State[EAX] = nextIns->dst;
  2869.                     Printf1("Optimization 34\n");
  2870.                 }
  2871.  
  2872.             else {
  2873.                 /*
  2874.                 Change
  2875.                 mov        %eax,%edi
  2876.                 push    %edi
  2877.                 with
  2878.                 push    %eax
  2879.                 */
  2880.                 if ( (notAlive) && (ins->Flags & ISMOVL) &&
  2881.                     !hasRegisterVariables &&
  2882.                     (nextIns->Name[0] == 'p' && nextIns->Name[1] == 'u') &&
  2883.                     (!strcmp(nextIns->src,"%edi"))) {
  2884.                     ChangeInstruction(nextIns,bb,nextIns->Name,"%eax","");
  2885.                     ins->Flags |= DELETED;
  2886.                     deleted++;
  2887.                     Printf1("Optimization 35\n");
  2888.                     return 2;
  2889.                 }
  2890.                 else if (hasRegisterVariables == 0 &&
  2891.                     idxInstruction == (bb->NrOfInstructions-1)) {
  2892.                     ins->Flags |= DELETED;
  2893.                     deleted++;
  2894.                     Printf1("Optimization 36\n");
  2895.                     return(1);
  2896.                 }
  2897.             }
  2898.         }
  2899.     }
  2900.     doclobber(old,aReg);
  2901.     old = Nullst;
  2902.     aReg = 10000;
  2903.     /*
  2904.     When storing into a register change the state accordingly. This provokes that
  2905.     only the LAST alias is saved. For instance:
  2906.  
  2907.         mov    -4(%ebp),%esi
  2908.         mov %esi,-20(%ebp)
  2909.  
  2910.     This will leave in State only '-20(%ebp)' at the ESI position, even if the
  2911.     reference to '-4(%ebp)' is still valid. The problem is that maintaining a
  2912.     state with aliases becomes hairy: any stores at a similar address will be
  2913.     difficult to catch.
  2914.     For instance:
  2915.         leal -4(%ebp),%edi
  2916.         pushl %edi
  2917.         call  _somefunction
  2918.  
  2919.     Now the value in edi could be wrong. This is why I do not store into the
  2920.     State any leal moves. In 99% of the cases this is too strong, and many
  2921.     optimizations that are possible are just not done because of this. The
  2922.     problem is that a compiler that generates good code in 99% of the cases
  2923.     is just buggy!
  2924.     */
  2925.     if (ins->Flags & ISLEAL) {
  2926.         doclobber(ins->src,10000);
  2927.         if (ins->SrcReg < ESP) {
  2928.             State[EAX] = Nullst;
  2929.             State[EBX] = Nullst;
  2930.             State[ECX] = Nullst;
  2931.             State[EDX] = Nullst;
  2932.             State[ESI] = Nullst;
  2933.             State[EDI] = Nullst;
  2934.         }
  2935.         src = Nullst;
  2936.         /* try to change
  2937.             lea (%esi,%edi),%edi
  2938.             movl %edi,%eax
  2939.  
  2940.             into
  2941.  
  2942.             lea (%esi,%edi),%eax
  2943.         */
  2944.         if ((nextIns->Flags & CHANGED) == 0 &&
  2945.             !hasRegisterVariables &&
  2946.             (ins->Flags & CHANGED) == 0 &&
  2947.             nextIns->SrcReg == ins->DstReg && (nextIns->Flags & ISMOVL) &&
  2948.             (nextIns->Flags & ISREGSRC) && (nextIns->Flags & ISREGDST)) {
  2949.             if (!IsAliveValue(bb,idxInstruction+2,ins->DstReg)) {
  2950.                 ChangeInstruction(ins,bb,opcode,ins->src,nextIns->dst);
  2951.                 nextIns->Flags |= DELETED;
  2952.                 deleted++;
  2953.                 Printf1("Optimization 27\n");
  2954.                 return(result+1);
  2955.             }
  2956.         }
  2957.         return result;
  2958.     }
  2959.     if (regsrc && isMovl && (ins->Flags & (DSTDEREFERENCE)) == 0) {
  2960.         aReg = ins->SrcReg;
  2961.         if (aReg > 0 && aReg < EBP) {
  2962.             unsigned char *d = dst;
  2963.             old = State[aReg];
  2964.             if (ins->Flags & DSTOFFSET && ins->DstReg != EBP) {
  2965.                 d = Nullst;
  2966.                 if ((nextIns->Flags & (DELETED|CHANGED)) == 0 &&
  2967.                     (ins->Flags & (DELETED|CHANGED)) == 0 &&
  2968.                     !strcmp(nextIns->Name,ins->Name) &&
  2969.                     !strcmp(nextIns->src,ins->dst)) {
  2970.                     ChangeInstruction(nextIns,bb,ins->Name,ins->src,nextIns->dst);
  2971.                     result++;
  2972.                 }
  2973.  
  2974.             }
  2975.             else 
  2976.             d = dst;
  2977.             State[aReg] = d;
  2978.             Printf3("%s = %s\n",RegisterNames[aReg],d);
  2979.             bb->Registers[aReg] = 1;
  2980.         }
  2981.     }
  2982.     /*
  2983.         Try to catch sequences like
  2984.             movl        %esi,   116(%edi)
  2985.             movl   116(%edi),        %esi
  2986.     */
  2987.     if (isMovl && regsrc && (regdst == 0)) {
  2988.         int flags;
  2989.  
  2990.         flags = nextIns->Flags;
  2991.         if ((flags & CHANGED)==0 &&(flags & ISMOVL) && !strcmp(nextIns->src,dst)) {
  2992.             if (nextIns->dst[0] == '%' && nextIns->DstReg == ins->SrcReg) {
  2993.                 nextIns->Flags |= DELETED;
  2994.                 deleted++;
  2995.                 Printf1("Cross redundant load\n");
  2996.             }
  2997.         }
  2998.  
  2999.     }
  3000.     if ((nextIns->Flags & (DELETED|CHANGED)) == 0 &&
  3001.         (ins->Flags & (DELETED|CHANGED)) == 0 &&
  3002.         ins->Name[0] == 'm' &&
  3003.         ins->Name[1] == 'o' &&
  3004.         !strcmp(nextIns->Name,ins->Name) &&
  3005.         !strcmp(nextIns->src,ins->dst) &&
  3006.         !strcmp(nextIns->dst,ins->src)) {
  3007.         nextIns->Flags |= DELETED;
  3008.         deleted++;
  3009.         Printf1("Cross redundant load\n");
  3010.     }
  3011.     if (aReg != 10000 || old != Nullst)
  3012.         doclobber(old,aReg);
  3013.     if (aReg != 10000) doclobber(dst,aReg);
  3014.     /*
  3015.     If a memory location has been written to with an immediate, this invalidates
  3016.     any caching to that location in the State table.
  3017.     */
  3018.     if (isImmediate && !regdst && ins->Name[0] == 'm' && ins->Name[1] == 'o' &&
  3019.         ins->Name[2] == 'v') {
  3020.         doclobber(dst,10000);
  3021.     }
  3022.     if (ins->Flags & ISCALL) {
  3023.         int i;
  3024.         i = call();
  3025.         if (i) return i;
  3026.     }
  3027.     return(result);
  3028. }
  3029. #ifndef ANALYZER
  3030. static int TransformJump(Instruction *fjump,Instruction *sjump,BasicBlock *bb)
  3031. {
  3032.     unsigned char *j = fjump->Name;
  3033.     unsigned char *newj = NULL;
  3034.     Instruction *insDst;
  3035.  
  3036.     j++;
  3037.     if (j[0] == 'g' && j[1] == 'e') {
  3038.         newj = "jl";
  3039.     }
  3040.     else if (j[0] == 'l') {
  3041.         if (j[1] == 'e')
  3042.             newj = "jg";
  3043.         else
  3044.             newj = "jge";
  3045.     }
  3046.     else if (j[0] == 'n' && j[1] == 'e')
  3047.         newj = "je";
  3048.     else if (j[0] == 'e')
  3049.         newj = "jne";
  3050.     else if (j[0] == 'g')
  3051.         newj = "jle";
  3052.     if (newj == NULL) {
  3053.         Printf2("Jump %s not found\n",fjump->Name);
  3054.         return(0);
  3055.     }
  3056.     insDst = GetNextChangedInstruction(fjump,bb);
  3057.     strcpy(insDst->Name,newj);
  3058.     strcpy(insDst->src,sjump->src);
  3059.     sjump->Flags |= DELETED;
  3060.     deleted++;
  3061.     return(1);
  3062. }
  3063. #endif
  3064. static int OptimizeBlock(void)
  3065. {
  3066.     Instruction *insDst;
  3067.     int i,f,last,nCalls;
  3068.  
  3069.     if (bb->NrOfInstructions == 0) return 0;
  3070.     Printf3("Block %s %d instructions\n",bb->Label,bb->NrOfInstructions);
  3071.     memset(State,0,sizeof(State));
  3072.     ins = InstructionTable;
  3073.     idxInstruction = last = 0;
  3074.     while (idxInstruction < bb->NrOfInstructions) {
  3075.         f = 1;
  3076.         if (ins->Name[0] != 'j') {
  3077.             int oldDeletedCount = deleted;
  3078.             f = FindStateChanges();
  3079.             bb->deleted += (deleted - oldDeletedCount);
  3080.         }
  3081.         idxInstruction += f;
  3082.         ins += f;
  3083.     }
  3084.     /*
  3085.         Try to replace a sequence of calls like:
  3086.             push    _var1
  3087.             push    _var2
  3088.             call    _someproc
  3089.             add        $8,%esp
  3090.             push    _var34
  3091.             push    _var36
  3092.             call    _someotherproc
  3093.             add        $8,%esp
  3094.             Eliminate all the additions to %esp and consolidate them in one
  3095.             addition at the end of the block. Rules:
  3096.             No intervening jumps (conditional or unconditional) should
  3097.             intervene, since that would leave the stack in a mess...
  3098.     */
  3099.     if ((hasAllocA == 0) &&
  3100.         bb->FirstCall < bb->LastCall &&
  3101.         bb->LastCall != bb->NrOfInstructions) {
  3102.         for (i=bb->FirstCall; i<=bb->LastCall;i++) {
  3103.             if (InstructionTable[i].Flags & ISCALL) {
  3104.                 unsigned char *Name = InstructionTable[i+1].Name;
  3105.                 unsigned char *dst = InstructionTable[i+1].dst;
  3106.                 if (Name[0] == 'a' &&
  3107.                     Name[1] == 'd' &&
  3108.                     dst[2] == 's' &&
  3109.                     dst[3] == 'p') {
  3110.                     InstructionTable[i].Flags |= STACKADJUST;
  3111.                 }
  3112.             }
  3113.         }
  3114.         ins = &InstructionTable[bb->FirstCall];
  3115.         f = 0;
  3116.         nCalls = 0;
  3117.         last = bb->FirstCall;
  3118.         for (i=bb->FirstCall;i <=bb->LastCall;i++) {
  3119.             if (ins->Flags & ISJUMP) {
  3120.                 ins = &InstructionTable[last+1];
  3121.                 break;
  3122.             }
  3123.             else if (ins->Flags & STACKADJUST) {
  3124.                 if (i == bb->NrOfInstructions-1) {
  3125.                     f = 1;
  3126.                     break;
  3127.                 }
  3128.                 ins++;
  3129.                 if (strcmp("addl",ins->Name) || (ins->Flags & CHANGED)) {
  3130.                     f = 1;
  3131.                     break;
  3132.                 }
  3133.                 else ins--;
  3134.                 last = i;
  3135.                 nCalls++;
  3136.             }
  3137.             ins++;
  3138.         }
  3139.         if (f == 0 && nCalls > 1) {
  3140.             char tbuf[6];
  3141.             Instruction *modify = ins;
  3142.             ins = &InstructionTable[bb->FirstCall];
  3143.             f = 0;
  3144.             for (i=bb->FirstCall;i <=last;i++) {
  3145.                 if (ins->Flags & STACKADJUST) {
  3146.                     ins++;
  3147.                     if (strcmp("addl",ins->Name)) {
  3148.                         Printf1("Bailout\n");
  3149.                         goto bailout;
  3150.                     }
  3151.                     f += atoi(&ins->src[1]);
  3152.                     if (i != last) {
  3153.                         ins->Flags |= DELETED;
  3154.                         deleted++;
  3155.                     }
  3156.                 }
  3157.                 else ins++;
  3158.             }
  3159.             modify = &InstructionTable[last+1];
  3160.             insDst = GetNextChangedInstruction(modify,bb);
  3161.             strcpy(insDst->Name,modify->Name);
  3162.             sprintf(tbuf,"$%d",f);
  3163.             strcpy(insDst->src,tbuf);
  3164.             strcpy(insDst->dst,modify->dst);
  3165.             Printf1("xxx\n");
  3166.         }
  3167.     }
  3168.     else if (bb->FirstCall && bb->FirstCall == bb->LastCall) {
  3169.         /* Replace
  3170.             add    $4,%esp    0x83c404 3 bytes
  3171.             with
  3172.             pop ecx 0x59 1 byte
  3173.         */
  3174.         ins = &InstructionTable[bb->LastCall+1];
  3175.         if (ins->Name[0] == 'a' && ins->src[0] == '$'
  3176.             && ins->src[1] == '4' &&
  3177.             !strcmp(ins->dst,"%esp") &&
  3178.             ins->src[2] == 0) {
  3179.             insDst = GetNextChangedInstruction(ins,bb);
  3180.             strcpy(insDst->Name,"pop");
  3181.             strcpy(insDst->src,"%ecx");
  3182.             Printf1("pop ecx\n");
  3183.  
  3184.         }
  3185.     }
  3186. bailout:
  3187. #ifdef DEBUGOPTIM
  3188.     i = 0;
  3189.     ins = InstructionTable;
  3190.     while (i < bb->NrOfInstructions) {
  3191.         int donewline;
  3192.  
  3193.         donewline = 1;
  3194.         if (ins->src[0] && ins->dst[0])
  3195.             Printf("[%2d]%8s%12s,%12s",
  3196.                 i+1,ins->Name,ins->src,ins->dst);
  3197.         else if (ins->src[0]) {
  3198.             Printf("[%2d]%8s%12s",
  3199.                 i+1,ins->Name,ins->src);
  3200.         }
  3201.         else {
  3202.             Printf("[%2d]%8s",
  3203.                 i+1,ins->Name);
  3204.         }
  3205.         if (ins->Flags & ISLOCAL) {
  3206.             Printf(" local");
  3207.         }
  3208.         if (ins->Flags & ISARGUMENT) {
  3209.             Printf(" argument");
  3210.         }
  3211.         if (ins->Flags & DELETED)
  3212.             Printf(" deleted");
  3213.         if (ins->Flags & CHANGED) {
  3214.             Instruction *insChanged;
  3215.             insChanged = &InstructionTable[ins->ChangedIdx];
  3216.             Printf(" %8s%12s,%12s",insChanged->Name,insChanged->src,insChanged->dst);
  3217.             if (insChanged->Flags & ADDED) {
  3218.                 insChanged = &InstructionTable[insChanged->ChangedIdx];
  3219.                 Printf("\n%s%s%s",insChanged->Name,insChanged->src,insChanged->dst);
  3220.                 donewline = 0;
  3221.             }
  3222.         }
  3223.         if (donewline) Printf("\n");
  3224.         i++;
  3225.         ins++;
  3226.     }
  3227.     Printf("Regs used: ");
  3228.     if (bb->Registers[EAX]) Printf("eax ");
  3229.     if (bb->Registers[EBX]) Printf("ebx ");
  3230.     if (bb->Registers[ECX]) Printf("ecx ");
  3231.     if (bb->Registers[EDX]) Printf("edx ");
  3232.     if (bb->Registers[EDI]) Printf("edi ");
  3233.     if (bb->Registers[ESI]) Printf("esi ");
  3234.     if (bb->Flags & ISCALL) Printf("First call %d, last %d",1+bb->FirstCall,1+bb->LastCall);
  3235.     if (last) printf(" last to adjust: %d",last+1);
  3236.     Printf("\n\n");
  3237. #endif
  3238.     return(1);
  3239. }
  3240. int FindEbpOffset(unsigned char *ins)
  3241. {
  3242.     int c,r;
  3243.     unsigned char *p = ins;
  3244.     if (*p == '-') p++;
  3245.     while (*p >= '0' && *p <= '9')
  3246.         p++;
  3247.     if (*p != '(') return(0);
  3248.     c = *p;
  3249.     if (p[1] != '%') return(0);
  3250.     *p = 0;
  3251.     r = atoi(ins);
  3252.     *p = c;
  3253.     return(r);
  3254. }
  3255. /*
  3256. This function tries to eliminate last dead stores from a block that ends with an
  3257. inconditional jmp to the last function label. This is not very much worth the effort:
  3258. 295574 to 295478
  3259. */
  3260. static int CheckLastJump(BasicBlock *bb)
  3261. {
  3262.     Instruction *ins;
  3263.     unsigned char *p;
  3264.     int labelNr,nrIns,TableOffsets[11],usedOffsets,offset;
  3265.  
  3266.     nrIns = bb->NrOfInstructions;
  3267.     if (nrIns <= 2 || hasRegisterVariables) return(2);
  3268.     nrIns--;
  3269.     ins = &InstructionTable[nrIns];
  3270.     if (ins->Flags & (CHANGED|DELETED)) return(0);
  3271.     p = ins->Name;
  3272.     if (p[0] == 'j' && p[1] == 'm' && p[2] == 'p') {
  3273.         p = ins->src;
  3274.         /* Test if the jump goes to the next instruction */
  3275.         if (!strncmp(p,ins->End,strlen(p))) {
  3276.             ins->Flags |= DELETED;
  3277.             deleted++;
  3278.             return 2;
  3279.         }
  3280.         labelNr = atoi(p+2);
  3281.         lastIns = &InstructionTable[nrIns-1];
  3282.         if (labelNr == lastLabel) {
  3283.             ins--;
  3284.             nrIns--;
  3285.             if (ins->Flags & (CHANGED|DELETED)) return(0);
  3286.             p = ins->Name;
  3287.             if (!strcmp(p,"movl")) {
  3288.                 if (ins->dst[0] == '%' && strcmp(ins->dst,"%eax")) {
  3289.                     ins->Flags |= DELETED;
  3290. //                    printf("%s %s %s\n",ins->Name,ins->src,ins->dst);
  3291.                     Printf1("Optimization 45\n");
  3292.                     return(1);
  3293.                 }
  3294.             }
  3295.             usedOffsets = 0;
  3296.             while (nrIns > 0) {
  3297.                 if (ins->Flags & (CHANGED|DELETED)) return(0);
  3298.                 if (ins->Flags & (ISCALL|ISJUMP|ISFLOAT)) break;
  3299.                 if (ins->SrcReg == EBP) {
  3300.                     if (usedOffsets > 10) break;
  3301.                     offset = FindEbpOffset(ins->src);
  3302.                     if (offset == 0) break;
  3303.                     TableOffsets[usedOffsets++] = offset;
  3304.                 }
  3305.                 if (ins->DstReg == EBP) {
  3306.                     int i;
  3307.  
  3308.                     offset = FindEbpOffset(ins->dst);
  3309.                     if (offset == 0) break;
  3310.                     for (i=0; i<usedOffsets;i++) {
  3311.                         if (TableOffsets[i] == offset)
  3312.                             return(2);
  3313.                     }
  3314.                     ins->Flags |= DELETED;
  3315. //                    printf("%s %s %s\n",ins->Name,ins->src,ins->dst);
  3316.                     Printf1("Optimization 46\n");
  3317.                     return(2);
  3318.                 }
  3319.                 nrIns--;
  3320.                 ins--;
  3321.             }
  3322.         }
  3323.     }
  3324.     return(2);
  3325. }
  3326. static int ChangeOutput(BasicBlock *bb,unsigned char *blockEnd,
  3327.                 int origlen,unsigned char **pnew,unsigned char *start)
  3328. {
  3329.     int i,len,l;
  3330.     Instruction *ins,*insChanged;
  3331.     unsigned char *p,*q,*newbuffer;
  3332.  
  3333.     if (bb->NrOfInstructions == 0) return 0;
  3334.     ins = InstructionTable;
  3335.     len = 3*origlen;
  3336.     newbuffer = malloc(len);
  3337.     memset(newbuffer,0,len);
  3338.     p = newbuffer;
  3339.     len = ins->Start - start;
  3340.     memcpy(p,start,len);
  3341.     p += len;
  3342.     i = 0;
  3343.     q = ins->Start;
  3344.     while (i < bb->NrOfInstructions) {
  3345.         if ((ins->Flags & (DELETED|CHANGED))==0) {
  3346.             l = ins->End - ins->Start;
  3347.             memcpy(p,ins->Start,l);
  3348.             p += l;
  3349.             q = ins->End;
  3350.         }
  3351.         else if ((ins->Flags & CHANGED) && (0==(ins->Flags&DELETED))) {
  3352.             *p++ = '\t';
  3353.             insChanged = &InstructionTable[ins->ChangedIdx];
  3354.             q = insChanged->Name;
  3355.             while (*q) {
  3356.                 *p++ = *q++;
  3357.             }
  3358.             q = insChanged->src;
  3359.             if (*q) *p++ = '\t';
  3360.             while (*q) {
  3361.                 *p++ = *q++;
  3362.             }
  3363.             if (insChanged->dst[0]) {
  3364.                 q = insChanged->dst;
  3365.                 *p++ = ',';
  3366.                 while (*q) {
  3367.                     *p++ = *q++;
  3368.                 }
  3369.             }
  3370.             *p++ = '\n';
  3371.             if (insChanged->Flags & ADDED) {
  3372.                 insChanged = &InstructionTable[insChanged->ChangedIdx];
  3373.                 q = insChanged->Name;
  3374.                 while (*q) {
  3375.                     *p++ = *q++;
  3376.                 }
  3377.                 q = insChanged->src;
  3378.                 while (*q) {
  3379.                     *p++ = *q++;
  3380.                 }
  3381.                 q = insChanged->dst;
  3382.                 while (*q) {
  3383.                     *p++ = *q++;
  3384.                 }
  3385.             }
  3386.             q = ins->End;
  3387.         }
  3388.         else if (ins->Flags & DELETED) {
  3389.             q = ins->End;
  3390.         }
  3391.         if (q < blockEnd) {
  3392.             while (*q == '\t' && q[1] == '.') {
  3393.                 while (*q && *q != '\n') {
  3394.                     *p++ = *q++;
  3395.                 }
  3396.                 if (*q == '\n') *p++ = *q++;
  3397.             }
  3398.             ins++;
  3399.             i++;
  3400.         }
  3401.         else break;
  3402.     }
  3403.     if (q < blockEnd) {
  3404.         l = blockEnd - q;
  3405.         memcpy(p,q,l);
  3406.         p += l;
  3407.     }
  3408.     len = p - newbuffer;
  3409.     *pnew = newbuffer;
  3410.     return(len);
  3411. }
  3412. #ifdef STANDALONE
  3413. /* for the STANDALONE program */
  3414. int ScanAsm(unsigned char *buffer,int len,unsigned char **poutput)
  3415. {
  3416.     BasicBlock block;
  3417.     unsigned char *bp,*q,*p,*stop,*newbuffer,*pnewbuffer,*output,*oldbp;
  3418.     int i,TotalInstructions,newlen,oldDeleted;
  3419.     long t = time(NULL);
  3420.  
  3421.     hasRegisterVariables = vmask[0];
  3422.     bp = buffer;
  3423.     stop = buffer+len;
  3424.     TotalInstructions = 0;
  3425.     *stop = 0;
  3426.     output = malloc(3*len);
  3427.     pnewbuffer = output;
  3428.     while (bp && bp<stop) {
  3429. restart:
  3430.         oldDeleted = deleted;
  3431.         memset(&block,0,sizeof(BasicBlock));
  3432.         InstructionIndex = 0;
  3433.         oldbp = bp;
  3434.         bp = FindBasicBlock(bp,&block,stop);
  3435.         memset(&InstructionTable[InstructionIndex],0,sizeof(Instruction));
  3436.         block.ChangedCounter = (unsigned short)InstructionIndex+1;
  3437.         TotalInstructions += block.NrOfInstructions;
  3438.         bb = █
  3439.         OptimizeBlock();
  3440.         if (bp) {
  3441.             newlen = ChangeOutput(&block,bp,bp-oldbp,&newbuffer,oldbp);
  3442.             memcpy(pnewbuffer,newbuffer,newlen);
  3443.             pnewbuffer += newlen;
  3444.         }
  3445.         else break;
  3446.         if (oldDeleted != deleted && bp) {
  3447.             unsigned char *nbp;
  3448.             memset(&block,0,sizeof(BasicBlock));
  3449.             InstructionIndex = 0;
  3450.             nbp = FindBasicBlock(pnewbuffer-newlen,&block,pnewbuffer);
  3451.             memset(&InstructionTable[InstructionIndex],0,sizeof(Instruction));
  3452.             block.ChangedCounter = (unsigned short)InstructionIndex+1;
  3453.             bb = █
  3454.             OptimizeBlock();
  3455.         }
  3456.     }
  3457.     *poutput = output;
  3458.     Printf3(" %d instructions in time %d\n",TotalInstructions,time(NULL)-t);
  3459.     return(pnewbuffer - output);
  3460. }
  3461. #else
  3462. /*
  3463. Here is the interface with the rest of lcc
  3464. */
  3465. extern int vmask[];
  3466. int ChangeBlock(unsigned char *buffer,int len)
  3467. {
  3468.     BasicBlock block;
  3469.     unsigned char *stop,*newbuffer;
  3470.     int l,oldDeleted,lastCheck=0;
  3471.  
  3472.     if (len == 0) return 0;
  3473.     lastLabel = GetLastFunctionLabel();
  3474.     recursion = 0;
  3475.     hasRegisterVariables = vmask[0];
  3476. restart:
  3477.     oldDeleted = deleted;
  3478.     stop = buffer + len;
  3479.     *stop = 0;
  3480.     memset(&block,0,sizeof(BasicBlock));
  3481.     InstructionIndex = 0;
  3482.     FindEndBlock(buffer,&block,stop);
  3483.     if (block.NrOfInstructions == 0) return(len);
  3484.     memset(&InstructionTable[InstructionIndex],0,sizeof(Instruction));
  3485.     block.ChangedCounter = (unsigned short) InstructionIndex+1;
  3486.     bb = █
  3487.     if (!OptimizeBlock())
  3488.         return(len);
  3489.     if (lastCheck < 2)
  3490.         lastCheck = CheckLastJump(&block);
  3491.     l = ChangeOutput(&block,buffer+len,len,&newbuffer,buffer);
  3492.     memcpy(buffer,newbuffer,l);
  3493.     if (len > l) {
  3494.         memset(&buffer[l],0,len-l);
  3495.     }
  3496.     free(newbuffer);
  3497.     if (oldDeleted != deleted || (block.ChangedCounter != InstructionIndex+1)) {
  3498.         len = l;
  3499.         recursion++;
  3500.         goto restart;
  3501.     }
  3502.     return(l);
  3503. }
  3504. #endif // STANDALONE
  3505.