home *** CD-ROM | disk | FTP | other *** search
/ CD Shareware Magazine 1996 December / CD_shareware_12-96.iso / DOS / Programa / CCDL122.ZIP / SOURCE / PEEP386.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-24  |  8.7 KB  |  338 lines

  1. /*
  2.  * 68K/386 32-bit C compiler.
  3.  *
  4.  * copyright (c) 1996, David Lindauer
  5.  * 
  6.  * This compiler is intended for educational use.  It may not be used
  7.  * for profit without the express written consent of the author.
  8.  *
  9.  * It may be freely redistributed, as long as this notice remains intact
  10.  * and sources are distributed along with any executables derived from them.
  11.  *
  12.  * The author is not responsible for damages, either direct or consequential,
  13.  * that may arise from use of this software.
  14.  *
  15.  * v1.5 August 1996
  16.  * David Lindauer, gclind01@starbase.spd.louisville.edu
  17.  *
  18.  * Credits to Mathew Brandt for original K&R C compiler
  19.  *
  20.  */
  21. #include        <stdio.h>
  22. #include        "expr.h"
  23. #include        "c.h"
  24. #include        "gen.h"
  25. #include        "cglbdec.h"
  26.  
  27. extern SYM *currentfunc;
  28. extern int funcfloat;
  29.  
  30. OCODE    *peep_head = 0,
  31.                 *peep_tail = 0;
  32.  
  33. void peepini(void)
  34. {
  35.     peep_head = peep_tail = 0;
  36. }
  37. AMODE    *copy_addr(AMODE *ap)
  38. /*
  39.  *      copy an address mode structure (these things dont last).
  40.  */
  41. {       AMODE    *newap;
  42.         if( ap == 0 )
  43.                 return 0;
  44.         newap = xalloc(sizeof(AMODE));
  45.         newap->mode = ap->mode;
  46.         newap->preg = ap->preg;
  47.         newap->sreg = ap->sreg;
  48.         newap->tempflag = ap->tempflag;
  49.         newap->offset = ap->offset;
  50.                 newap->scale = ap->scale;
  51.         return newap;
  52. }
  53.  
  54. void gen_code(int op,int len,AMODE *ap1,AMODE *ap2)
  55. /*
  56.  *      generate a code sequence into the peep list.
  57.  */
  58. {       OCODE    *new;
  59.         new = xalloc(sizeof(OCODE));
  60.         new->opcode = op;
  61.                 if (len < 0)
  62.             new->length = -len;
  63.                 else
  64.             new->length = len;
  65.                 new->length2 = new->length;
  66.         new->oper1 = copy_addr(ap1);
  67.         new->oper2 = copy_addr(ap2);
  68.         add_peep(new);
  69. }
  70. void gen_line(SNODE *stmt)
  71. {
  72.                 OCODE *new = xalloc(sizeof(OCODE));
  73.                 new->opcode = op_line;
  74.                 new->length = (int)stmt->exp;
  75.                 new->oper1 = (AMODE *)stmt->label;
  76.                 new->oper2 = 0;
  77.                 new->oper3= 0;
  78.                 add_peep(new);
  79. }
  80. void gen_codef(int op, int len, AMODE *ap1, AMODE *ap2)
  81. {
  82.   if (ap1->mode == am_freg && ap2->mode == am_freg)
  83.         len=10;
  84.     funcfloat++;
  85.     gen_code(op,len,ap1,ap2);
  86. }
  87. void gen_code2(int op, int len, int len2, AMODE *ap1, AMODE *ap2)
  88. {
  89.         OCODE    *new;
  90.         new = xalloc(sizeof(OCODE));
  91.         new->opcode = op;
  92.                 if (len < 0)
  93.             new->length = -len;
  94.                 else
  95.             new->length = len;
  96.                 if (len2 < 0)
  97.             new->length2 = -len2;
  98.                 else
  99.             new->length2 = len2;
  100.         new->oper1 = copy_addr(ap1);
  101.         new->oper2 = copy_addr(ap2);
  102.         add_peep(new);
  103. }
  104.  
  105.  
  106. void add_peep(OCODE *new)
  107. /*
  108.  *      add the ocoderuction pointed to by new to the peep list.
  109.  */
  110. {       if( peep_head == 0 )
  111.                 {
  112.                 peep_head = peep_tail = new;
  113.                 new->fwd = 0;
  114.                 new->back = 0;
  115.                 }
  116.         else
  117.                 {
  118.                 new->fwd = 0;
  119.                 new->back = peep_tail;
  120.                 peep_tail->fwd = new;
  121.                 peep_tail = new;
  122.                 }
  123. }
  124.  
  125. void gen_label(int labno)
  126. /*
  127.  *      add a compiler generated label to the peep list.
  128.  */
  129. {       OCODE    *new;
  130.         new = xalloc(sizeof(OCODE));
  131.         new->opcode = op_label;
  132.         new->oper1 = (AMODE *)labno;
  133.         add_peep(new);
  134. }
  135.  
  136. void flush_peep(void)
  137. /*
  138.  *      output all code and labels in the peep list.
  139.  */
  140. {       opt3();         /* do the peephole optimizations */
  141.         while( peep_head != 0 )
  142.                 {
  143.                 if( peep_head->opcode == op_label )
  144.                         put_label((int)peep_head->oper1);
  145.                 else
  146.                         put_ocode(peep_head);
  147.                 peep_head = peep_head->fwd;
  148.                 }
  149.                 dump_muldivval();
  150. }
  151.  
  152. void put_ocode(OCODE *p)
  153. /*
  154.  *      output the instruction passed.
  155.  */
  156. {       put_code(p->opcode,p->length,p->length2,p->oper1,p->oper2);
  157. }
  158.  
  159. void peep_add(OCODE *ip)
  160. /*
  161.  * Turn add,1 into inc
  162.  */
  163. {
  164.     if (ip->oper2->mode != am_immed || ip->oper2->offset->nodetype != en_icon)
  165.         return;
  166.     if (ip->oper2->offset->v.i == 1) {
  167.         ip->opcode = op_inc;
  168.         ip->oper2 = 0;
  169.     }
  170.     return;
  171. }
  172. /*
  173.  * Turn sub,1 into dec
  174.  */
  175. void peep_sub(OCODE *ip)
  176. {
  177.     if (ip->oper2->mode != am_immed || ip->oper2->offset->nodetype != en_icon)
  178.         return;
  179.     if (ip->oper2->offset->v.i == 1) {
  180.         ip->opcode = op_dec;
  181.         ip->oper2 = 0;
  182.     }
  183.     return;
  184. }
  185. /*
  186.  * Turn move reg,0 into sub reg,reg
  187.  */
  188. void peep_move(OCODE *ip)
  189. {
  190.     if (ip->oper1->mode != am_dreg || 
  191.                 ip->oper2->mode != am_immed || ip->oper2->offset->nodetype != en_icon)
  192.         return;
  193.     if (ip->oper2->offset->v.i == 0) {
  194.         ip->opcode = op_sub;
  195.         ip->oper2 = ip->oper1;
  196.     }
  197.     return;
  198. }
  199. /*
  200.  * delete or reg,reg preceded by an instruction that already sets flags
  201.  */
  202. void peep_or(OCODE *ip)
  203. {
  204.     OCODE *ip2;
  205.     if ((ip->oper1->mode != ip->oper2->mode) || ip->oper1->mode != am_dreg ||
  206.                 (ip->oper1->preg != ip->oper2->preg))
  207.         return;
  208.     ip2 = ip->back;
  209.     if (ip2->oper1->mode != am_dreg || ip2->oper1->preg != ip->oper1->preg)
  210.         return;
  211.     if (ip2->opcode != op_sub && ip2->opcode != op_add && ip2->opcode != op_inc
  212.             && ip2->opcode != op_dec && ip2->opcode != op_and && ip2->opcode != op_or
  213.             && ip2->opcode != op_xor)
  214.         return;
  215.     ip2->fwd = ip->fwd;
  216.     ip->fwd->back = ip->back;
  217. }
  218.  
  219. void peep_uctran(OCODE *ip)
  220. /*
  221.  *      peephole optimization for unconditional transfers.
  222.  *      deletes instructions which have no path.
  223.  *      applies to bra, jmp, and rts instructions.
  224.  */
  225. {       while( ip->fwd != 0 && ip->fwd->opcode != op_label )
  226.                 {
  227.                 ip->fwd = ip->fwd->fwd;
  228.                 if( ip->fwd != 0 )
  229.                         ip->fwd->back = ip;
  230.                 }
  231. }
  232. void peep_label(OCODE *ip)
  233. /*
  234.  *        peephole optimization for labels
  235.  *        deletes relbranches that jump to the next instruction
  236.  */
  237. {
  238.             OCODE *curpos, *index;
  239.             curpos = ip;
  240.             do {
  241.                 curpos = curpos->back;
  242.             } while(curpos->opcode == op_label);
  243.             while ((curpos->opcode == op_jmp) || curpos->opcode == op_cmp
  244.                         || curpos->opcode == op_test 
  245.                         || (curpos->opcode == op_jne) || (curpos->opcode == op_je) 
  246.                         || (curpos->opcode == op_jge) || (curpos->opcode == op_jle) 
  247.                         || (curpos->opcode == op_jg) || (curpos->opcode == op_jl) 
  248.                         || (curpos->opcode == op_jnc) || (curpos->opcode == op_jbe) 
  249.                         || (curpos->opcode == op_ja) || (curpos->opcode == op_jb) ) {
  250.                 index = curpos->fwd;
  251.                 if (curpos->opcode == op_cmp
  252.                                 || curpos->opcode == op_test) {
  253.                         curpos->back->fwd = curpos->fwd;
  254.                         curpos->fwd->back = curpos->back;
  255.                         curpos = curpos->back;
  256.                 }
  257.                 else {
  258.                     do {
  259.                         if ((index->oper1->mode == am_immed) && ((int)index->oper1 == curpos->oper1->offset->v.i)) {
  260.                             curpos->back->fwd = curpos->fwd;
  261.                             curpos->fwd->back = curpos->back;
  262.                             curpos = curpos->back;
  263.                             break;
  264.                         }
  265.                         index = index->fwd;
  266.                     } while (index != ip->fwd);
  267.                     if (index == ip->fwd)
  268.                         break;
  269.                 }
  270.                 while(curpos->opcode == op_label)
  271.                     curpos = curpos->back;
  272.             }
  273. }
  274. int equal_address(AMODE *ap1,AMODE *ap2)
  275. {
  276.     if (ap1->mode != ap2->mode)
  277.         return(FALSE);
  278.     switch (ap1->mode) {
  279.         case am_indispscale:
  280.                         if (ap1->scale != ap2->scale || ap1->sreg != ap2->sreg)
  281.                             return(FALSE);
  282.         case am_indisp:
  283.                         if (ap1->offset)
  284.                             if (ap2->offset) {
  285.                                 if (ap1->offset->v.i != ap2->offset->v.i)
  286.                                     return(FALSE);
  287.                             }
  288.                             else
  289.                                 return(FALSE);
  290.                         else
  291.                             if (ap2->offset)
  292.                                 return(FALSE);
  293.         case am_dreg:
  294.         case am_freg:
  295.                         if (ap1->preg != ap2->preg)
  296.                             return(FALSE);
  297.                         break;
  298.                     
  299.         case am_direct:
  300.                         return FALSE;
  301.     }
  302.     return(TRUE);
  303. }
  304.  
  305. void opt3(void)
  306. /*
  307.  *      peephole optimizer. This routine calls the instruction
  308.  *      specific optimization routines above for each instruction
  309.  *      in the peep list.
  310.  */
  311. {       OCODE    *ip;
  312.         ip = peep_head;
  313.         while( ip != 0 )
  314.                 {
  315.                 switch( ip->opcode )
  316.                         {
  317.                                                 case op_label:
  318.                                                                 peep_label(ip);
  319.                                                                 break;
  320.                                                 case op_add:
  321.                                                                 peep_add(ip);
  322.                                                                 break;
  323.                                                 case op_sub:
  324.                                                                 peep_sub(ip);
  325.                                                                 break;
  326.                                                 case op_mov:
  327.                                                                 peep_move(ip);
  328.                                                                 break;
  329.                                                 case op_or:
  330.                                                                 peep_or(ip);
  331.                                                                 break;
  332.                         case op_jmp:
  333.                         case op_ret:
  334.                                 peep_uctran(ip);
  335.                         }
  336.                 ip = ip->fwd;
  337.                 }
  338. }