home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d110 / pdc.lha / Pdc / src / Peepgen.c < prev    next >
C/C++ Source or Header  |  1987-10-28  |  11KB  |  368 lines

  1. #include        <stdio.h>
  2. #include        "c.h"
  3. #include        "expr.h"
  4. #include        "gen.h"
  5. #include        "cglbdec.h"
  6.  
  7. /*
  8.  *68000 C compiler
  9.  *
  10.  *Copyright 1984, 1985, 1986 Matthew Brandt.
  11.  *  all commercial rights reserved.
  12.  *
  13.  *This compiler is intended as an instructive tool for personal use. Any
  14.  *use for profit without the written consent of the author is prohibited.
  15.  *
  16.  *This compiler may be distributed freely for non-commercial use as long
  17.  *as this notice stays intact. Please forward any enhancements or questions
  18.  *to:
  19.  *
  20.  *Matthew Brandt
  21.  *Box 920337
  22.  *Norcross, Ga 30092
  23.  */
  24.  
  25. struct ocode    *peep_head = 0,
  26.                 *peep_tail = 0;
  27.  
  28. struct amode    *copy_addr(ap)
  29. /*
  30.  *      copy an address mode structure (these things dont last).
  31.  */
  32. struct amode    *ap;
  33. {       struct amode    *newap;
  34.         if( ap == 0 )
  35.                 return 0;
  36.         newap = xalloc(sizeof(struct amode));
  37.         newap->mode = ap->mode;
  38.         newap->preg = ap->preg;
  39.         newap->sreg = ap->sreg;
  40.         newap->tempflag = ap->tempflag;
  41.         newap->deep = ap->deep;
  42.         newap->offset = ap->offset;
  43.         return newap;
  44. }
  45.  
  46. gen_code(op,len,ap1,ap2)
  47. /*
  48.  *      generate a code sequence into the peep list.
  49.  */
  50. enum e_op    op;
  51. int             len;
  52. struct amode    *ap1, *ap2;
  53. {       struct ocode    *new;
  54.         new = xalloc(sizeof(struct ocode));
  55.         new->opcode = op;
  56.         new->length = len;
  57.         new->oper1 = copy_addr(ap1);
  58.         new->oper2 = copy_addr(ap2);
  59.         add_peep(new);
  60. }
  61.  
  62. add_peep(new)
  63. /*
  64.  *      add the ocoderuction pointed to by new to the peep list.
  65.  */
  66. struct ocode    *new;
  67. {       if( peep_head == 0 )
  68.                 {
  69.                 peep_head = peep_tail = new;
  70.                 new->fwd = 0;
  71.                 new->back = 0;
  72.                 }
  73.         else
  74.                 {
  75.                 new->fwd = 0;
  76.                 new->back = peep_tail;
  77.                 peep_tail->fwd = new;
  78.                 peep_tail = new;
  79.                 }
  80. }
  81.  
  82. gen_label(labno)
  83. /*
  84.  *      add a compiler generated label to the peep list.
  85.  */
  86. int    labno;
  87. {       struct ocode    *new;
  88.         new = xalloc(sizeof(struct ocode));
  89.         new->opcode = op_label;
  90.         new->oper1 = (struct amode *)labno;
  91.         add_peep(new);
  92. }
  93.  
  94. flush_peep()
  95. /*
  96.  *      output all code and labels in the peep list.
  97.  */
  98. {
  99.         if ( Options.Optimize )
  100.            opt3();     /* do the peephole optimizations */
  101.         while( peep_head != 0 )
  102.                 {
  103.                 if( peep_head->opcode == op_label )
  104.                         put_label((long)(peep_head->oper1));
  105.                 else
  106.                         put_ocode(peep_head);
  107.                 peep_head = peep_head->fwd;
  108.                 }
  109. }
  110.  
  111. put_ocode(p)
  112. /*
  113.  *      output the instruction passed.
  114.  */
  115. struct ocode    *p;
  116. {       put_code(p->opcode,p->length,p->oper1,p->oper2);
  117. }
  118.  
  119. peep_move(ip)
  120. /*
  121.  *      peephole optimization for move instructions.
  122.  *      makes quick immediates when possible.
  123.  *      changes move #0,d to clr d.
  124.  *      changes long moves to address registers to short when
  125.  *              possible.
  126.  *      changes move immediate to stack to pea.
  127.  */
  128. struct ocode *ip;
  129. {       struct enode    *ep;
  130.         if( ip->oper1->mode != am_immed )
  131.                 return;
  132.         ep = ip->oper1->offset;
  133.         if( ep->nodetype != en_icon )
  134.                 return;
  135.         if( ip->oper2->mode == am_areg )
  136.                 {
  137.                 if( -32768 <= ep->v.i && ep->v.i <= 32768 )
  138.                         ip->length = 2;
  139.                 }
  140.         else if( ip->oper2->mode == am_dreg )
  141.                 {
  142.                 if( -128 <= ep->v.i && ep->v.i <= 127 )
  143.                         {
  144.                         ip->opcode = op_moveq;
  145.                         ip->length = 0;
  146.                         }
  147.                 }
  148.         else
  149.                 {
  150.                 if( ep->v.i == 0 )
  151.                         {
  152.                         ip->opcode = op_clr;
  153.                         ip->oper1 = ip->oper2;
  154.                         ip->oper2 = 0;
  155.                         }
  156.                 else if( ip->oper2->mode == am_adec && (int)(ip->oper2)->preg == 7 )
  157.                         {
  158.                         ip->opcode = op_pea;
  159.                         ip->length = 0;
  160.                         ip->oper1->mode = am_direct;
  161.                         ip->oper2 = 0;
  162.                         }
  163.                 }
  164. }
  165.  
  166. int     equal_address(ap1,ap2)
  167. /*
  168.  *      compare two address nodes and return true if they are
  169.  *      equivalent.
  170.  */
  171. struct amode    *ap1, *ap2;
  172. {       if( ap1 == 0 || ap2 == 0 )
  173.                 return 0;
  174.         if( ap1->mode != ap2->mode )
  175.                 return 0;
  176.         switch( ap1->mode )
  177.                 {
  178.                 case am_areg:   case am_dreg:
  179.                 case am_ainc:   case am_adec:
  180.                         return ap1->preg == ap2->preg;
  181.                 }
  182.         return 0;
  183. }
  184.  
  185. peep_add(ip)
  186. /*
  187.  *      peephole optimization for add instructions.
  188.  *      makes quick immediates out of small constants.
  189.  */
  190. struct ocode    *ip;
  191. {       struct enode    *ep;
  192.         if( ip->oper1->mode != am_immed )
  193.                 return;
  194.         ep = ip->oper1->offset;
  195.         if( ip->oper2->mode != am_areg )
  196.                 ip->opcode = op_addi;
  197.         else
  198.                 {
  199.                 if( isshort(ep) )
  200.                         ip->length = 2;
  201.                 }
  202.         if( ep->nodetype != en_icon )
  203.                 return;
  204.         if( 1 <= ep->v.i && ep->v.i <= 8 )
  205.                 ip->opcode = op_addq;
  206.         else if( -8 <= ep->v.i && ep->v.i <= -1 )
  207.                 {
  208.                 ip->opcode = op_subq;
  209.                 ep->v.i = -ep->v.i;
  210.                 }
  211. }
  212.  
  213. peep_sub(ip)
  214. /*
  215.  *      peephole optimization for subtract instructions.
  216.  *      makes quick immediates out of small constants.
  217.  */
  218. struct ocode    *ip;
  219. {       struct enode    *ep;
  220.         if( ip->oper1->mode != am_immed )
  221.                 return;
  222.         ep = ip->oper1->offset;
  223.         if( ip->oper2->mode != am_areg )
  224.                 ip->opcode = op_subi;
  225.         else
  226.                 {
  227.                 if( isshort(ep) )
  228.                         ip->length = 2;
  229.                 }
  230.         if( ep->nodetype != en_icon )
  231.                 return;
  232.         if( 1 <= ep->v.i && ep->v.i <= 8 )
  233.                 ip->opcode = op_subq;
  234.         else if( -8 <= ep->v.i && ep->v.i <= -1 )
  235.                 {
  236.                 ip->opcode = op_addq;
  237.                 ep->v.i = -ep->v.i;
  238.                 }
  239. }
  240.  
  241. int     peep_cmp(ip)
  242. /*
  243.  *      peephole optimization for compare instructions.
  244.  *      changes compare #0 to tst and if previous instruction
  245.  *      should have set the condition codes properly delete.
  246.  *      return value is true if instruction was deleted.
  247.  */
  248. struct ocode    *ip;
  249. {       struct ocode    *prev;
  250.         struct enode    *ep;
  251.         if( ip->oper1->mode != am_immed )
  252.                 return;
  253.         ep = ip->oper1->offset;
  254.         if( ip->oper2->mode == am_areg )
  255.                 {
  256.                 if( isshort(ep) )
  257.                         ip->length = 2;
  258.                 return;
  259.                 }
  260.         ip->opcode = op_cmpi;
  261.         if( ep->nodetype != en_icon || ep->v.i != 0 )
  262.                 return;
  263.         ip->oper1 = ip->oper2;
  264.         ip->oper2 = 0;
  265.         ip->opcode = op_tst;
  266.         prev = ip->back;
  267.         if( prev == 0 )
  268.                 return;
  269.         if( (((prev->opcode == op_move || prev->opcode == op_moveq) &&
  270.                 equal_address(prev->oper1,ip->oper1)) &&
  271.                 prev->oper2->mode != am_areg) ||
  272.                 (prev->opcode != op_label &&
  273.                 equal_address(prev->oper2,ip->oper1)) )
  274.                 {
  275.                 prev->fwd = ip->fwd;
  276.                 if( prev->fwd != 0 )
  277.                         prev->fwd->back = prev;
  278.                 }
  279. }
  280.  
  281. peep_muldiv(ip,op)
  282. /*
  283.  *      changes multiplies and divides by convienient values
  284.  *      to shift operations. op should be either op_asl or
  285.  *      op_asr (for divide).
  286.  */
  287. struct ocode    *ip;
  288. enum e_op    op;
  289. {       int     shcnt;
  290.         if( ip->oper1->mode != am_immed )
  291.                 return;
  292.         if( ip->oper1->offset->nodetype != en_icon )
  293.                 return;
  294.         switch( shcnt = (int)(ip->oper1->offset->v.i) )
  295.       {
  296.             case 2: shcnt = 1; break;
  297.             case 4: shcnt = 2; break;
  298.             case 8: shcnt = 3; break;
  299.             case 16: shcnt = 4; break;
  300.             case 32: shcnt = 5; break;
  301.             case 64: shcnt = 6; break;
  302.             case 128: shcnt = 7; break;
  303.             case 256: shcnt = 8; break;
  304.             case 512: shcnt = 9; break;
  305.             case 1024: shcnt = 10; break;
  306.             case 2048: shcnt = 11; break;
  307.             case 4096: shcnt = 12; break;
  308.             case 8192: shcnt = 13; break;
  309.             case 16384: shcnt = 14; break;
  310.             default: return;
  311.           }
  312.         ip->oper1->offset->v.i = shcnt;
  313.         ip->opcode = op;
  314.         ip->length = 4;
  315. }
  316.  
  317. peep_uctran(ip)
  318. /*
  319.  *      peephole optimization for unconditional transfers.
  320.  *      deletes instructions which have no path.
  321.  *      applies to bra, jmp, and rts instructions.
  322.  */
  323. struct ocode    *ip;
  324. {       while( ip->fwd != 0 && ip->fwd->opcode != op_label )
  325.                 {
  326.                 ip->fwd = ip->fwd->fwd;
  327.                 if( ip->fwd != 0 )
  328.                         ip->fwd->back = ip;
  329.                 }
  330. }
  331.  
  332. opt3()
  333. /*
  334.  *      peephole optimizer. This routine calls the instruction
  335.  *      specific optimization routines above for each instruction
  336.  *      in the peep list.
  337.  */
  338. {       struct ocode    *ip;
  339.         ip = peep_head;
  340.         while( ip != 0 )
  341.                 {
  342.                 switch( ip->opcode )
  343.                         {
  344.                         case op_move:
  345.                                 peep_move(ip);
  346.                                 break;
  347.                         case op_add:
  348.                                 peep_add(ip);
  349.                                 break;
  350.                         case op_sub:
  351.                                 peep_sub(ip);
  352.                                 break;
  353.                         case op_cmp:
  354.                                 peep_cmp(ip);
  355.                                 break;
  356.                         case op_muls:
  357.                                 peep_muldiv(ip,op_asl);
  358.                                 break;
  359.                         case op_bra:
  360.                         case op_jmp:
  361.                         case op_rts:
  362.                                 peep_uctran(ip);
  363.                         }
  364.                 ip = ip->fwd;
  365.                 }
  366. }
  367.  
  368.