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

编译器/解释器

开发平台:

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. #include        <stdio.h>
  23. #include        "expr.h"
  24. #include        "c.h"
  25. #include        "gen386.h"
  26. /*
  27.  *      this module handles the allocation and de-allocation of
  28.  *      temporary registers. when a temporary register is allocated
  29.  *      the stack depth is saved in the field deep of the address
  30.  *      mode structure. when validate is called on an address mode
  31.  *      structure the stack is popped until the register is restored
  32.  *      to it's pre-push value.
  33.  */
  34. extern int cf_freedata,cf_freeaddress,cf_freefloat;
  35. AMODE push[1],pop[1];
  36. int             next_data, /* Next available */
  37.                 next_addr;
  38. int             max_data, /* Max available */
  39.                 max_addr;
  40. int next_float, max_float;
  41. long stackdepth,framedepth;
  42. int regs[3];
  43. char regstack[20],rsold[30],rsdepth = 0,rsodepth=0;
  44. void regini(void)
  45. {
  46. rsdepth = rsodepth = 0;
  47. }
  48. void gen_push(int reg, int rmode, int flag)
  49. /*
  50.  *      this routine generates code to push a register onto the stack
  51.  */
  52. {       AMODE    *ap1;
  53.         ap1 = xalloc(sizeof(AMODE));
  54.         ap1->preg = reg;
  55.         ap1->mode = rmode;
  56. if (rmode == am_freg) {
  57. FLOAT;
  58. }
  59. else {
  60.           gen_code(op_push,4,ap1,0);
  61. if (flag)
  62. framedepth+=4;
  63. else
  64. stackdepth +=4;
  65. }
  66. }
  67. void gen_pop(int reg, int rmode, int flag)
  68. /*
  69.  *      generate code to pop the primary register in ap from the
  70.  *      stack.
  71.  */
  72. {       AMODE    *ap1;
  73.         ap1 = xalloc(sizeof(AMODE));
  74.         ap1->preg = reg;
  75.         ap1->mode = rmode;
  76. if (rmode == am_freg) {
  77. FLOAT;
  78. }
  79. else {
  80.          gen_code(op_pop,4,ap1,0);
  81. stackdepth -=4;
  82. }
  83. }
  84. void pushregs(unsigned mask)
  85. {
  86. int i;
  87. int umask = 0x08000;
  88. for (i=0; i < 4; i++) {
  89. if (umask & mask)
  90. gen_push(i,am_dreg,1);
  91. umask >>=1;
  92. }
  93. umask = 0x080;
  94. for (i=4; i < 8; i++) {
  95. if (umask & mask)
  96. gen_push(i,am_dreg,1);
  97. umask >>=1;
  98. }
  99. }
  100. /* This is ONLY called from the return.  Calling from any other place
  101.  * will leave the stack depth unpredictable... */
  102. void popregs(unsigned mask)
  103. {
  104. int i;
  105. int umask = 0x800;
  106. for (i=7; i >= 4; i--) {
  107. if (umask & mask) {
  108. gen_pop(i,am_dreg,1);
  109. stackdepth+=4;
  110. }
  111. umask >>=1;
  112. }
  113. umask = 0x8;
  114. for (i=3; i >= 0; i--) {
  115. if (umask & mask) {
  116. gen_pop(i,am_dreg,1);
  117. stackdepth+=4;
  118. }
  119. umask >>=1;
  120. }
  121. }
  122. void initstack(void)
  123. /*
  124.  *      this routine should be called before each expression is
  125.  *      evaluated to make sure the stack is balanced and all of
  126.  *      the registers are marked free.
  127.  */
  128. {
  129. rsdepth = rsodepth = 0;
  130.        next_data = 0;
  131.         next_addr = 0;
  132.         max_data = cf_freedata-1;
  133.         max_addr = cf_freeaddress-1;
  134. next_float = 0;
  135. max_float = cf_freefloat-1;
  136. regs[0]=regs[1]=regs[2]=0;
  137. }
  138. void mark(void)
  139. {
  140. rsold[rsodepth++] = rsdepth;
  141. }
  142. void release(void)
  143. {
  144. if (!rsodepth)
  145. return;
  146. rsodepth--;
  147. while (rsdepth > rsold[rsodepth]) {
  148. int data = regstack[--rsdepth];
  149.   gen_pop(data,am_dreg,0);
  150. }
  151. }
  152. AMODE    *temp_data(void)
  153. /*
  154.  *      allocate a temporary data register and return it's
  155.  *      addressing mode.
  156.  */
  157. {       AMODE    *ap;
  158.         ap = xalloc(sizeof(AMODE));
  159.         ap->mode = am_dreg;
  160.         ap->preg = next_data % cf_freedata;
  161.         if( next_data > max_data )
  162.                 {
  163.                 gen_push(ap->preg,am_dreg,0);
  164. regstack[rsdepth++] = ap->preg;
  165. regs[ap->preg]--;
  166.                 max_data = next_data;
  167.                 }
  168. regs[ap->preg]++;
  169.         ++next_data;
  170.         return ap;
  171. }
  172. void freedata(int dreg)
  173. {
  174. if (dreg < cf_freedata && next_data > 0) {
  175. --next_data;
  176. regs[dreg]--;
  177. }
  178. }
  179. void freeaddr(int areg)
  180. {
  181. if (areg < cf_freeaddress && next_addr > 0) 
  182. --next_addr;
  183. }
  184. void freeop(AMODE *ap)
  185. /*
  186.  *      release any temporary registers used in an addressing mode.
  187.  */
  188. {       if( ap->mode == am_immed || ap->mode == am_direct )
  189.                 return;         /* no registers used */
  190.         if( ap->mode == am_dreg)
  191. freedata(ap->preg);
  192.   else if (ap->mode == am_indisp)
  193. freedata(ap->preg);
  194.   else if (ap->mode == am_indispscale) {
  195. freedata(ap->preg);
  196. freedata(ap->sreg);
  197. }
  198. }