PEEP68.C
上传用户:hlzzc88
上传日期:2007-01-06
资源大小:220k
文件大小:18k
源码类别:

编译器/解释器

开发平台:

Others

  1. /*
  2.  * 68K/386 32-bit C compiler.
  3.  *
  4.  * copyright (c) 1997, 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 either the original sources or derived sources 
  11.  * are distributed along with any executables derived from the originals.
  12.  *
  13.  * The author is not responsible for any damages that may arise from use
  14.  * of this software, either idirect or consequential.
  15.  *
  16.  * v1.35 March 1997
  17.  * David Lindauer, gclind01@starbase.spd.louisville.edu
  18.  *
  19.  * Credits to Mathew Brandt for original K&R C compiler
  20.  *
  21.  */
  22. /*
  23.  * peepcode optimizations
  24.  */
  25. #include        <stdio.h>
  26. #include        "expr.h"
  27. #include        "c.h"
  28. #include        "gen68.h"
  29. #include  "diag.h"
  30. extern SYM *currentfunc;
  31. OCODE    *peep_head = 0,
  32.                 *peep_tail = 0,
  33. *peep_insert;
  34. extern int prm_buggyclr;
  35. void peepini(void)
  36. {
  37. peep_head = peep_tail = 0;
  38. }
  39. AMODE    *copy_addr(AMODE *ap)
  40. /*
  41.  *      copy an address mode structure (these things dont last).
  42.  */
  43. {       AMODE    *newap;
  44.         if( ap == 0 )
  45.                 return 0;
  46.         newap = xalloc(sizeof(AMODE));
  47.         newap->mode = ap->mode;
  48.         newap->preg = ap->preg;
  49.         newap->sreg = ap->sreg;
  50. newap->scale = ap->scale;
  51.         newap->tempflag = ap->tempflag;
  52.         newap->offset = ap->offset;
  53.         return newap;
  54. }
  55. void gen_code(int op,int len,AMODE *ap1,AMODE *ap2)
  56. /*
  57.  *      generate a code sequence into the peep list.
  58.  */
  59. {       OCODE    *new;
  60.         new = xalloc(sizeof(OCODE));
  61.         new->opcode = op;
  62. if (len < 0)
  63.          new->length = -len;
  64. else
  65.          new->length = len;
  66.         new->oper1 = copy_addr(ap1);
  67.         new->oper2 = copy_addr(ap2);
  68. new->oper3 = 0;
  69.         add_peep(new);
  70. }
  71. void gen_lea(int size, AMODE *ap1, AMODE * ap2)
  72. {
  73. AMODE *ap3,*ap4;
  74. if (ap1->mode== am_ainc || ap1->mode == am_adec) {
  75. enum e_am om = ap1->mode;
  76. if (!size) {
  77. size = 1;
  78. DIAG("Illegal len in autoinc lea");
  79. }
  80. if (size < 0) size = - size;
  81.   ap1->mode = am_ind;
  82. ap3 = copy_addr(ap1);
  83. ap3->mode = am_areg;
  84. ap4 = make_immed(size);
  85. gen_code(op_move,4,ap3,ap2);
  86. if (om == am_ainc)
  87. gen_code(op_add,4,ap4,ap3);
  88. else
  89. gen_code(op_sub,4,ap4,ap3);
  90. ap1->mode = om;
  91. }
  92. else
  93. if (ap2->mode == am_areg) {
  94. if (ap1->mode == am_baseindxaddr && !ap1->scale) {
  95. if (ap1->preg == ap2->preg && !ap1->offset->v.i) {
  96. ap3 = xalloc(sizeof(AMODE));
  97. ap3->mode = am_areg;
  98. ap3->preg = ap1->sreg;
  99. gen_code(op_add,4,ap3,ap2);
  100. }
  101. else if (ap1->sreg == ap2->preg && !ap1->offset->v.i) {
  102. ap3 = xalloc(sizeof(AMODE));
  103. ap3->mode = am_areg;
  104. ap3->preg = ap1->preg;
  105. gen_code(op_add,4,ap3,ap2);
  106. }
  107. else 
  108. gen_code(op_lea,size,ap1,ap2);
  109. }
  110. else if (ap1->mode == am_baseindxdata && !ap1->offset->v.i && !ap1->scale) {
  111. if (ap1->preg == ap2->preg) {
  112. ap3 = xalloc(sizeof(AMODE));
  113. ap3->mode = am_dreg;
  114. ap3->preg = ap1->sreg;
  115. gen_code(op_add,4,ap3,ap2);
  116. }
  117. else
  118. gen_code(op_lea,0,ap1,ap2);
  119. }
  120. else
  121. gen_code(op_lea,0,ap1,ap2);
  122. }
  123. else  
  124. gen_code(op_lea,0,ap1,ap2);
  125. }
  126. void gen_codelab(SYM *lab)
  127. /*
  128.  *      generate a code sequence into the peep list.
  129.  */
  130. {       OCODE    *new;
  131.         new = xalloc(sizeof(OCODE));
  132.         new->opcode = op_funclabel;
  133.         new->length = 0;
  134.         new->oper1 = lab;
  135.         new->oper2 = 0;
  136. new->oper3 = 0;
  137.         add_peep(new);
  138. }
  139. void gen_line(SNODE *stmt)
  140. {
  141. OCODE *new = xalloc(sizeof(OCODE));
  142. new->opcode = op_line;
  143. new->length = (int)stmt->exp;
  144. new->oper1 = (AMODE *)stmt->label;
  145. new->oper2 = 0;
  146. new->oper3= 0;
  147. add_peep(new);
  148. }
  149. void gen_codef(int op, int len, AMODE *ap1, AMODE *ap2)
  150. {
  151.   if (ap1->mode == am_freg) {
  152. if (!ap2 || ap2->mode == am_freg)
  153. len=10;
  154. }
  155. else if (ap2 && ap2->mode == am_freg) {
  156. if (ap1->mode == am_immed)
  157. len = 10;
  158. }
  159. gen_code(op,len,ap1,ap2);
  160. }
  161. void gen_code3(int op, int len, AMODE *ap1, AMODE *ap2, AMODE *ap3)
  162. {       OCODE    *new;
  163.         new = xalloc(sizeof(OCODE));
  164.         new->opcode = op;
  165. if (len < 0)
  166.          new->length = -len;
  167. else
  168.          new->length = len;
  169.         new->oper1 = copy_addr(ap1);
  170.         new->oper2 = copy_addr(ap2);
  171. new->oper3 = copy_addr(ap3);
  172.         add_peep(new);
  173. }
  174. void add_peep(OCODE *new)
  175. /*
  176.  *      add the ocoderuction pointed to by new to the peep list.
  177.  */
  178. {       if( peep_head == 0 )
  179.                 {
  180.                 peep_head = peep_tail = new;
  181.                 new->fwd = 0;
  182.                 new->back = 0;
  183.                 }
  184.         else
  185.                 {
  186.                 new->fwd = 0;
  187.                 new->back = peep_tail;
  188.                 peep_tail->fwd = new;
  189.                 peep_tail = new;
  190.                 }
  191. }
  192. void gen_label(int labno)
  193. /*
  194.  *      add a compiler generated label to the peep list.
  195.  */
  196. {       OCODE    *new;
  197.         new = xalloc(sizeof(OCODE));
  198.         new->opcode = op_label;
  199.         new->oper1 = (AMODE *)labno;
  200.         add_peep(new);
  201. }
  202. void flush_peep(void)
  203. /*
  204.  *      output all code and labels in the peep list.
  205.  */
  206. {       opt3();         /* do the peephole optimizations */
  207.         while( peep_head != 0 )
  208.                 {
  209.                 if( peep_head->opcode == op_label )
  210.                         put_label(peep_head);
  211.                 else
  212. if (peep_head->opcode == op_funclabel)
  213. gen_strlab(peep_head->oper1);
  214. else
  215.                         put_code(peep_head);
  216.                 peep_head = peep_head->fwd;
  217.                 }
  218. /* oc_reorgfunc(); */
  219. peep_head = 0;
  220. }
  221. void peep_move(OCODE *ip)
  222. /*
  223.  *      peephole optimization for move instructions.
  224.  *      makes quick immediates when possible.
  225.  *      changes move #0,d to clr d.
  226.  *      changes long moves to address registers to short when
  227.  *              possible.
  228.  *      changes move immediate to stack to pea.
  229.  */
  230. {       ENODE    *ep;
  231. if (ip->noopt)
  232. return;
  233. if (ip->oper2->mode == am_areg)
  234. ip->opcode = op_movea;
  235.         if( ip->oper1->mode != am_immed )
  236.                 return;
  237.         ep = ip->oper1->offset;
  238.         if( !isintconst(ep->nodetype))
  239.                 return;
  240.         if( ip->oper2->mode == am_areg )
  241.                 {
  242.                 if( -32768L <= ep->v.i && ep->v.i <= 32768L )
  243.                         ip->length = 2;
  244.                 }
  245.         else if( ip->oper2->mode == am_dreg )
  246.                 {
  247.                 if( -128 <= ep->v.i && ep->v.i <= 127 )
  248.                         {
  249.                         ip->opcode = op_moveq;
  250.                         ip->length = 0;
  251.                         }
  252.                 }
  253.         else
  254.                 {
  255.                 if( ep->v.i == 0 && !prm_buggyclr)
  256.                         {
  257.                         ip->opcode = op_clr;
  258.                         ip->oper1 = ip->oper2;
  259.                         ip->oper2 = 0;
  260.                         }
  261.                 else if( ip->oper2->mode == am_adec && ip->oper2->preg == 7 )
  262.                         {
  263.                         ip->opcode = op_pea;       
  264.                         ip->length = 0;
  265.                         ip->oper1->mode = am_direct;
  266.                         ip->oper2 = 0;
  267.                         }
  268.                 }
  269. }
  270. /*
  271.  * get rid of a TST after any other instruction that sets flags if the
  272.  * args match
  273.  */
  274. int peep_tst(OCODE *ip)
  275. {
  276. if (ip->noopt)
  277. return;
  278. if (ip->back->opcode == op_move || ip->back->opcode == op_and || ip->back->opcode == op_or ||
  279. ip->back->opcode == op_andi || ip->back->opcode == op_ori || ip->back->opcode == op_add ||
  280. ip->back->opcode == op_addi || ip->back->opcode == op_addq || ip->back->opcode == op_sub ||
  281. ip->back->opcode == op_subi || ip->back->opcode == op_subq) {
  282. if (equal_address(ip->back->oper2,ip->oper1)) {
  283. ip->back->fwd = ip->fwd;
  284. ip->fwd->back = ip->back;
  285. }
  286. }
  287. }
  288. int     equal_address(AMODE *ap1, AMODE *ap2)
  289. /*
  290.  *      compare two address nodes and return true if they are
  291.  *      equivalent.
  292.  */
  293. {       if( ap1 == 0 || ap2 == 0 )
  294.                 return 0;
  295.         if( ap1->mode != ap2->mode )
  296.                 return 0;
  297.         switch( ap1->mode )
  298.                 {
  299.                 case am_areg:   case am_dreg:
  300.                 case am_ainc:   case am_adec:
  301.                         return ap1->preg == ap2->preg;
  302. case am_baseindxaddr:
  303. case am_baseindxdata:
  304. case am_indx:
  305. if (ap1->preg != ap2->preg)
  306. return FALSE;
  307. if (ap1->sreg != ap2->sreg)
  308. return FALSE;
  309. return equalnode(ap1->offset,ap2->offset);
  310. case am_immed:
  311. case am_direct:
  312. case am_adirect:
  313. case am_pcindx:
  314. return equalnode(ap1->offset,ap2->offset);
  315.                 }
  316.         return 0;
  317. }
  318. void peep_add(OCODE *ip)
  319. /*
  320.  *      peephole optimization for add instructions.
  321.  *      makes quick immediates out of small constants.
  322.  */
  323. {       ENODE    *ep;
  324. if (ip->noopt)
  325. return;
  326. if (ip->oper2->mode == am_areg)
  327. ip->opcode = op_adda;
  328.         if( ip->oper1->mode != am_immed )
  329.                 return;
  330.         ep = ip->oper1->offset;
  331.         if( ip->oper2->mode != am_areg )
  332.                 ip->opcode = op_addi;
  333.         else
  334.                 {
  335.                 if( isshort(ep) )
  336.                         ip->length = 2;
  337.                 }
  338.         if( !(isintconst(ep->nodetype)))
  339.                 return;
  340.         if( 1 <= ep->v.i && ep->v.i <= 8 )
  341.                 ip->opcode = op_addq;
  342.         else if( -8 <= ep->v.i && ep->v.i <= -1 )
  343.                 {
  344.                 ip->opcode = op_subq;
  345.                 ep->v.i = -ep->v.i;
  346.                 }
  347. }
  348. void peep_sub(OCODE *ip)
  349. /*
  350.  *      peephole optimization for subtract instructions.
  351.  *      makes quick immediates out of small constants.
  352.  */
  353. {       ENODE    *ep;
  354. if (ip->noopt)
  355. return;
  356. if (ip->oper2->mode == am_areg)
  357. ip->opcode = op_suba;
  358.         if( ip->oper1->mode != am_immed )
  359.                 return;
  360.         ep = ip->oper1->offset;
  361.         if( ip->oper2->mode != am_areg )
  362.                 ip->opcode = op_subi;
  363.         else
  364.                 {
  365.                 if( isshort(ep) )
  366.                         ip->length = 2;
  367.                 }
  368.         if(!isintconst( ep->nodetype) )
  369.                 return;
  370.         if( 1 <= ep->v.i && ep->v.i <= 8 ) {
  371.                 ip->opcode = op_subq;
  372. if (ip->oper2->mode == am_areg && ip->length <=4 && ip->fwd->oper1->mode == am_ind && ip->oper2->preg == ip->fwd->oper1->preg) {
  373. int sz1 = ip->fwd->length;
  374. int sz2 = ep->v.i;
  375. if (sz1 < 0) sz1 = -sz1;
  376. if (sz2 < 0) sz2 = -sz2;
  377. if (sz2 == sz1) {
  378. ip->back->fwd = ip->fwd;
  379. ip->fwd->back = ip->back;
  380. ip->fwd->oper1->mode = am_adec;
  381. }
  382. }
  383. }
  384.         else if( -8 <= ep->v.i && ep->v.i <= -1 )
  385.                 {
  386.                 ip->opcode = op_addq;
  387.                 ep->v.i = -ep->v.i;
  388.                 }
  389. }
  390. void     peep_cmp(OCODE *ip)
  391. /*
  392.  *      peephole optimization for compare instructions.
  393.  *      changes compare #0 to tst and if previous instruction
  394.  *      should have set the condition codes properly delete.
  395.  *      return value is true if instruction was deleted.
  396.  */
  397. {       OCODE    *prev=0;
  398.         ENODE    *ep;
  399. if (ip->noopt)
  400. return;
  401. if (ip->oper2->mode == am_areg)
  402. ip->opcode = op_cmpa;
  403.         if( ip->oper1->mode == am_immed ) {
  404.         ep = ip->oper1->offset;
  405.          if( ip->oper2->mode == am_areg )
  406.                  {
  407.                  if( isshort(ep) )
  408.                          ip->length = 2;
  409.                  return;
  410.                  }
  411.         ip->opcode = op_cmpi;
  412.          if( isintconst(ep->nodetype) &&  ep->v.i == 0 ) {
  413. if (ip->fwd->opcode == op_bne || ip->fwd->opcode == op_beq ) {
  414.         ip->oper1 = ip->oper2;
  415.            ip->oper2 = 0;
  416.            ip->opcode = op_tst;
  417.          prev = ip->back;
  418. }
  419. }
  420. }
  421.      if( prev == 0)
  422.                 return;
  423.         if( (((prev->opcode == op_move || prev->opcode == op_moveq
  424. || prev->opcode == op_add || prev->opcode == op_addi
  425. || prev->opcode == op_sub || prev->opcode == op_subi
  426. || prev->opcode == op_addq || prev->opcode == op_subq) &&
  427.               equal_address(prev->oper1,ip->oper1)) &&
  428.                 prev->oper2->mode != am_areg) ||
  429.                 (prev->opcode != op_label &&
  430.                 equal_address(prev->oper2,ip->oper1)) )
  431.                 {
  432.                 prev->fwd = ip->fwd;
  433.                 if( prev->fwd != 0 )
  434.                         prev->fwd->back = prev;
  435.                 }
  436. }
  437. void peep_muldiv(OCODE *ip, int op)
  438. /*
  439.  *      changes multiplies and divides by convienient values
  440.  *      to shift operations. op should be either op_asl or
  441.  *      op_asr (for divide).
  442.  */
  443. {       int     shcnt;
  444. if (ip->noopt)
  445. return;
  446.         if( ip->oper1->mode != am_immed )
  447.                 return;
  448.         if(!isintconst( ip->oper1->offset->nodetype ))
  449.                 return;
  450.         shcnt = ip->oper1->offset->v.i;
  451. /*      vax c doesn't do this type of switch well       */
  452.         if( shcnt == 2) shcnt = 1;
  453.         else if( shcnt == 4) shcnt = 2;
  454.         else if( shcnt == 8) shcnt = 3;
  455.         else if( shcnt == 16) shcnt = 4;
  456.         else if( shcnt == 32) shcnt = 5;
  457.         else if( shcnt == 64) shcnt = 6;
  458.         else if( shcnt == 128) shcnt = 7;
  459.         else if( shcnt == 256) shcnt = 8;
  460.         else if( shcnt == 512) shcnt = 9;
  461.         else if( shcnt == 1024) shcnt = 10;
  462.         else if( shcnt == 2048) shcnt = 11;
  463.         else if( shcnt == 4096) shcnt = 12;
  464.         else if( shcnt == 8192) shcnt = 13;
  465.         else if( shcnt == 16384) shcnt = 14;
  466.         else return;
  467.         ip->oper1->offset->v.i = shcnt;
  468.         ip->opcode = op;
  469.         ip->length = 4;
  470. }
  471. void peep_uctran(OCODE *ip)
  472. /*
  473.  *      peephole optimization for unconditional transfers.
  474.  *      deletes instructions which have no path.
  475.  *      applies to bra, jmp, and rts instructions.
  476.  */
  477. {       while( ip->fwd != 0 && ip->fwd->opcode != op_label )
  478.                 {
  479.                 ip->fwd = ip->fwd->fwd;
  480.                 if( ip->fwd != 0 )
  481.                         ip->fwd->back = ip;
  482.                 }
  483. }
  484. void peep_label(OCODE *ip)
  485. /*
  486.  * peephole optimization for labels
  487.  * deletes relbranches that jump to the next instruction
  488.  */
  489. {
  490. OCODE *curpos, *index;
  491. curpos = ip;
  492. if (!curpos->back)
  493. return;
  494. do {
  495. curpos = curpos->back;
  496. } while(curpos->opcode == op_label || curpos->opcode == op_line);
  497. while ((curpos->opcode == op_bra) || curpos->opcode == op_cmp
  498. || curpos->opcode == op_cmpi || curpos->opcode == op_tst 
  499. || (curpos->opcode == op_bne) || (curpos->opcode == op_beq) 
  500. || (curpos->opcode == op_bge) || (curpos->opcode == op_ble) 
  501. || (curpos->opcode == op_bgt) || (curpos->opcode == op_blt) 
  502. || (curpos->opcode == op_bhs) || (curpos->opcode == op_bls) 
  503. || (curpos->opcode == op_bhi) || (curpos->opcode == op_blo) ) {
  504. index = curpos->fwd;
  505. if (ip->noopt)
  506. return;
  507. if ((curpos->opcode == op_cmpi || curpos->opcode == op_cmp
  508. || curpos->opcode == op_tst )) {
  509. if (curpos->fwd->opcode == op_label) {
  510. curpos->back->fwd = curpos->fwd;
  511. curpos->fwd->back = curpos->back;
  512. curpos = curpos->back;
  513. }
  514. else
  515. break;
  516. }
  517. else {
  518. do {
  519. if ((index->opcode == op_label) && (curpos->oper1->mode == am_direct) && ((int)index->oper1 == curpos->oper1->offset->v.i)) {
  520. curpos->back->fwd = curpos->fwd;
  521. curpos->fwd->back = curpos->back;
  522. curpos = curpos->back;
  523. break;
  524. }
  525. index = index->fwd;
  526. } while (index != ip->fwd);
  527. if (index == ip->fwd)
  528. break;
  529. }
  530. while(curpos->opcode == op_label || curpos->opcode == op_line)
  531. curpos = curpos->back;
  532. }
  533. }
  534. void opt3(void)
  535. /*
  536.  *      peephole optimizer. This routine calls the instruction
  537.  *      specific optimization routines above for each instruction
  538.  *      in the peep list.
  539.  */
  540. {       OCODE    *ip=peep_head;
  541.         while( ip != 0 )
  542.                 {
  543. if (ip->opcode != op_line && ip->opcode != op_label && ip->opcode != op_slit) {
  544. if (ip->oper1 && ip->oper1->mode == am_indx && ip->oper1->offset->v.i == 0)
  545. ip->oper1->mode = am_ind;
  546. if (ip->oper2 && ip->oper2->mode == am_indx && ip->oper2->offset->v.i == 0)
  547. ip->oper2->mode = am_ind;
  548. }
  549.                 switch( ip->opcode )
  550.                         {
  551.                         case op_move:
  552.                                 peep_move(ip);
  553.                                 break;
  554.                         case op_add:
  555.                                 peep_add(ip);
  556.                                 break;
  557.                         case op_sub:
  558.                                 peep_sub(ip);
  559.                                 break;
  560. case op_tst:
  561. peep_tst(ip);
  562. break;
  563.                         case op_cmp:
  564.                                 peep_cmp(ip);
  565.                                 break;
  566. case op_and:
  567. if (ip->oper1->mode == am_immed)
  568. ip->opcode = op_andi;
  569. break;
  570. case op_or:
  571. if (ip->oper1->mode == am_immed)
  572. ip->opcode = op_ori;
  573. break;
  574. case op_eor:
  575. if (ip->oper1->mode == am_immed)
  576. ip->opcode = op_eori;
  577. break;
  578.                         case op_muls:
  579.                                 peep_muldiv(ip,op_asl);
  580.                                 break;
  581. case op_label:
  582. peep_label(ip);
  583. break;
  584.                         case op_bra:
  585.                         case op_jmp:
  586.                         case op_rts:
  587.                                 peep_uctran(ip);
  588.                         }
  589.                 ip = ip->fwd;
  590.                 }
  591. }