home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / misc / amigem.lha / amigem / genglue / machine.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-08  |  3.5 KB  |  177 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include "genglue.h"
  4. #include "machine.h"
  5.  
  6. char *regnames[]=
  7. { "d0","d1","d2","d3","d4","d5","d6","d7",
  8.   "a0","a1","a2","a3","a4","a5","a6","sp" };
  9.  
  10. void printvar(char *name)
  11. {
  12.   if(baserel)
  13.     printf("a4@(");
  14.   printf("_%s%s",precedevec,name);
  15.   if(baserel)
  16.     printf(":W)");
  17. }
  18.  
  19. int regnum(int c)
  20. {
  21.   if(!isxdigit(c))
  22.     return -1;
  23.   else
  24.     return isdigit(c)?c-'0':islower(c)?c-'a'+0xa:c-'A'+0xa;
  25. }
  26.  
  27. int pushregs(int mask)
  28. {
  29.   int i,c=0;
  30.   for(i=0;i<16;i++)
  31.     if(mask&(0x8000>>i))
  32.       c++;
  33.   if(c<3)
  34.   {
  35.     for(i=0;i<16;i++)
  36.       if(mask&(0x8000>>i))
  37.         printf("\tmovel %s,sp@-\n",regnames[i]);
  38.   }else
  39.     printf("\tmoveml #0x%04x,sp@-\n",mask);
  40.   return c;
  41. }
  42.  
  43. int popregs(int mask)
  44. {
  45.   int i,c=0;
  46.   for(i=0;i<16;i++)
  47.     if(mask&(0x8000>>i))
  48.       c++;
  49.   if(c<3)
  50.   {
  51.     for(i=16;i-->0;)
  52.       if(mask&(0x8000>>i))
  53.         printf("\tmovel sp@+,%s\n",regnames[i]);
  54.   }else
  55.   {
  56.     int newmask=0;
  57.     for(i=0;i<16;i++)
  58.     {
  59.       newmask<<=1;
  60.       newmask|=(mask&1);
  61.       mask>>=1;
  62.     }
  63.     printf("\tmoveml sp@+,#0x%04x\n",newmask);
  64.   }
  65.   return c;
  66. }
  67.  
  68. void genlabel(void)
  69. {
  70.   printf("\t.even\n");
  71.   printf("\t.globl _%s%s\n",precede,namebuf);
  72.   printf("_%s%s:\n",precede,namebuf);
  73. }
  74.  
  75. void regmask(int *mask)
  76. {
  77.   int i;
  78.   for(i=0;i<regbufcnt;i++)
  79.   {
  80.     if(*mask&(0x8000>>regbuf[i]))
  81.       ERROR("Duplicate argument register");
  82.     *mask|=0x8000>>regbuf[i];
  83.   }
  84. }
  85.  
  86. int allocreg(int *mask)
  87. {
  88.   int i;
  89.   int reg[15]={ 8,9,0,1,2,3,4,5,6,7,0xa,0xb,0xc,0xd,0xe };
  90.   for(i=0;i<15;i++)
  91.     if(!(*mask&(0x8000>>reg[i])))
  92.     {
  93.       *mask|=0x8000>>reg[i];
  94.       return reg[i];
  95.     }
  96.   ERROR("No free register");
  97. }
  98.  
  99. void normglue(void)
  100. {
  101.   int i,c;
  102.   int sparg,mask;
  103.  
  104.   if(!basepar&&!libbasevar[0])
  105.     ERROR("missing base variable");
  106.   mask=0x8000>>libbasereg; /* Mask of arguments */
  107.   regmask(&mask);
  108.   sparg=0;
  109.   if(mask&0x0001)
  110.   { for(i=0;i<regbufcnt;i++)
  111.       if(regbuf[i]==15)
  112.         sparg=i+1;
  113.     mask&=0xfffe; }
  114.   mask|=(preserve<-1?0x3f38:0)+(preserve<0?0x0006:0)+
  115.         (preserve<1?0x00c0:0)+(preserve<2?0xc000:0);
  116.   if(sparg)
  117.     regbuf[sparg-1]=allocreg(&mask);
  118.   genlabel();
  119.   mask&=0x3f3f;
  120.   c=pushregs(mask);
  121.   if(!basepar)
  122.   {
  123.     printf("\tmovel ");
  124.     printvar(libbasevar);
  125.     printf(",%s\n",regnames[libbasereg]);
  126.   }else
  127.     printf("\tmovel sp@(%ld:W),%s\n",(c+1)*sizeof(long),regnames[libbasereg]);
  128.   for(i=0;i<regbufcnt;i++)
  129.     printf("\tmovel sp@(%ld:W),%s\n",(c+i+1+basepar)*sizeof(long),regnames[regbuf[i]]);
  130.   if(sparg)
  131.     printf("\texg %s,sp\n",regnames[regbuf[sparg-1]]);
  132.   printf("\tjsr %s@",regnames[libbasereg]);
  133.   if(liboffset>0)
  134.     printf("(-%d:W)",liboffset*6);
  135.   printf("\n");
  136.   if(sparg)
  137.     printf("\tmovel %s,sp\n",regnames[regbuf[sparg-1]]);
  138.   if(iflag)
  139.     printf("\tsne d0\n\textw d0\n\textl d0\n");
  140.   popregs(mask);
  141.   printf("\trts\n");
  142. }
  143.  
  144. void reverseglue(void)
  145. {
  146.   int i,c,mask;
  147.   genlabel();
  148.   mask=(preserve>0?0x00c0:0)+(preserve>1?0xc000:0)+(baserel?8:0);
  149.   c=1+pushregs(mask);
  150.   for(i=regbufcnt;i-->0;)
  151.   {
  152.     printf("\tmovel %s,sp@-\n",regnames[regbuf[i]]);
  153.     c++;
  154.     if(regbuf[i]==15)
  155.     {
  156.       if(c<4)
  157.         printf("\taddql #%d,sp@\n",c*4-4);
  158.       else
  159.         printf("\taddl #%d:W,sp@\n",c*4-4);
  160.     }
  161.   }
  162.   if(basepar)
  163.     printf("\tmovel %s,sp@-\n",regnames[libbasereg]);
  164.   if(baserel)
  165.     printf("\tjbsr ___geta4\n");
  166.   printf("\tjbsr _%s%s\n",precedevec,namebuf);
  167.   c=regbufcnt+basepar;
  168.   if(c>2)
  169.     printf("\taddaw #%d,sp\n",c*4);
  170.   else if(c)
  171.     printf("\taddqw #%d,sp\n",c*4);
  172.   popregs(mask);
  173.   if(iflag)
  174.     printf("\tmovel #0xdff000,a0\n\ttstl d0\n");
  175.   printf("\trts\n");
  176. }
  177.