home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 338_02 / register.c < prev    next >
Text File  |  1979-12-31  |  5KB  |  162 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. /*
  26.  *      this module handles the allocation and de-allocation of
  27.  *      temporary registers. when a temporary register is allocated
  28.  *      the stack depth is saved in the field deep of the address
  29.  *      mode structure. when validate is called on an address mode
  30.  *      structure the stack is popped until the register is restored
  31.  *      to it's pre-push value.
  32.  */
  33.  
  34. struct amode    push[] = { {am_adec,7} },
  35.                 pop[] = { {am_ainc,7} };
  36. int             next_data,
  37.                 next_addr;
  38. int             max_data,
  39.                 max_addr;
  40.  
  41. gen_push(reg,rmode)
  42. /*
  43.  *      this routine generates code to push a register onto the stack
  44.  */
  45. int     reg, rmode;
  46. {       struct amode    *ap1;
  47.         ap1 = xalloc(sizeof(struct amode));
  48.         ap1->preg = reg;
  49.         ap1->mode = rmode;
  50.         gen_code(op_move,4,ap1,push);
  51. }
  52.  
  53. gen_pop(reg,rmode)
  54. /*
  55.  *      generate code to pop the primary register in ap from the
  56.  *      stack.
  57.  */
  58. int     reg, rmode;
  59. {       struct amode    *ap1;
  60.         ap1 = xalloc(sizeof(struct amode));
  61.         ap1->preg = reg;
  62.         ap1->mode = rmode;
  63.         gen_code(op_move,4,pop,ap1);
  64. }
  65.  
  66. initstack()
  67. /*
  68.  *      this routine should be called before each expression is
  69.  *      evaluated to make sure the stack is balanced and all of
  70.  *      the registers are marked free.
  71.  */
  72. {       next_data = 0;
  73.         next_addr = 0;
  74.         max_data = 2;
  75.         max_addr = 1;
  76. }
  77.  
  78. validate(ap)
  79. /*
  80.  *      validate will make sure that if a register within an address
  81.  *      mode has been pushed onto the stack that it is popped back
  82.  *      at this time.
  83.  */
  84. struct amode    *ap;
  85. {       switch( ap->mode )
  86.                 {
  87.                 case am_direct:
  88.                 case am_immed:
  89.                         return;         /* no registers used */
  90.                 case am_dreg:
  91.                         if( ap->preg > 2 )
  92.                                 return; /* not a temporary */
  93.                         if( max_data - ap->deep >= 3 )
  94.                                 {
  95.                                 gen_pop(ap->preg,am_dreg);
  96.                                 --max_data;
  97.                                 }
  98.                         break;
  99.                 default:
  100.                         if( ap->preg > 1 )
  101.                                 return; /* not a temp register */
  102.                         if( max_addr - ap->deep >= 2 )
  103.                                 {
  104.                                 gen_pop(ap->preg,am_areg);
  105.                                 --max_addr;
  106.                                 }
  107.                         break;
  108.                 }
  109. }
  110.  
  111. struct amode    *temp_data()
  112. /*
  113.  *      allocate a temporary data register and return it's
  114.  *      addressing mode.
  115.  */
  116. {       struct amode    *ap;
  117.         ap = xalloc(sizeof(struct amode));
  118.         ap->mode = am_dreg;
  119.         ap->preg = next_data % 3;
  120.         ap->deep = next_data;
  121.         if( next_data > max_data )
  122.                 {
  123.                 gen_push(next_data % 3,am_dreg);
  124.                 max_data = next_data;
  125.                 }
  126.         ++next_data;
  127.         return ap;
  128. }
  129.  
  130. struct amode    *temp_addr()
  131. /*
  132.  *      allocate a temporary address register and return it's
  133.  *      addressing mode.
  134.  */
  135. {       struct amode    *ap;
  136.         ap = xalloc(sizeof(struct amode));
  137.         ap->mode = am_areg;
  138.         ap->preg = next_addr % 2;
  139.         ap->deep = next_addr;
  140.         if( next_addr > max_addr )
  141.                 {
  142.                 gen_push(next_addr % 2,am_areg);
  143.                 max_addr = next_addr;
  144.                 }
  145.         ++next_addr;
  146.         return ap;
  147. }
  148.  
  149. freeop(ap)
  150. /*
  151.  *      release any temporary registers used in an addressing mode.
  152.  */
  153. struct amode    *ap;
  154. {       if( ap->mode == am_immed || ap->mode == am_direct )
  155.                 return;         /* no registers used */
  156.         if( ap->mode == am_dreg && ap->preg < 3 )
  157.                 --next_data;
  158.         else if( ap->preg < 2 )
  159.                 --next_addr;
  160. }
  161.  
  162.