home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 338_02 / outcode.c < prev    next >
Text File  |  1989-11-29  |  13KB  |  450 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. /*      variable initialization         */
  26.  
  27. enum e_gt { nogen, bytegen, wordgen, longgen };
  28. enum e_sg { noseg, codeseg, dataseg };
  29.  
  30. extern int echo;
  31.  
  32. int           gentype = nogen;
  33. int           curseg = noseg;
  34. int        outcol = 0;
  35.  
  36. struct oplst {
  37.         char    *s;
  38.         int     ov;
  39.         }       opl[] =
  40.         {       {"move",op_move}, {"move",op_moveq}, {"add",op_add},
  41.                 {"add",op_addi}, {"add",op_addq}, {"sub",op_sub},
  42.                 {"sub",op_subi}, {"sub",op_subq}, {"and",op_and},
  43.                 {"or",op_or}, {"eor",op_eor}, {"muls",op_muls},
  44.                 {"divs",op_divs}, {"swap",op_swap}, {"beq",op_beq},
  45.                 {"bhi",op_bhi}, {"bhs",op_bhs}, {"blo",op_blo},
  46.                 {"bls",op_bls}, {"mulu",op_mulu}, {"divu",op_divu},
  47.                 {"bne",op_bne}, {"blt",op_blt}, {"ble",op_ble},
  48.                 {"bgt",op_bgt}, {"bge",op_bge}, {"neg",op_neg},
  49.                 {"not",op_not}, {"cmp",op_cmp}, {"ext",op_ext},
  50.                 {"jmp",op_jmp}, {"jsr",op_jsr}, {"rts",op_rts},
  51.                 {"lea",op_lea}, {"asr",op_asr}, {"asl",op_asl},
  52.                 {"clr",op_clr}, {"link",op_link}, {"unlk",op_unlk},
  53.                 {"bra",op_bra}, {"movem",op_movem}, {"pea",op_pea},
  54.                 {"cmp",op_cmpi}, {"tst",op_tst}, {"dc",op_dc},
  55.                 {0,0} };
  56.  
  57. putop(op)
  58. int     op;
  59. {       int     i;
  60.         i = 0;
  61.         while( opl[i].s )
  62.                 {
  63.                 if( opl[i].ov == op )
  64.                         {
  65.                         fprintf(output,"\t%s",opl[i].s);
  66.                         if( echo )
  67.                             fprintf(stdout,"\t%s",opl[i].s);
  68.                         return;
  69.                         }
  70.                 ++i;
  71.                 }
  72.         printf("DIAG - illegal opcode.\n");
  73. }
  74.  
  75. putconst(offset) /* put a constant to the output file. */
  76. struct enode    *offset;
  77. {       switch( offset->nodetype )
  78.                 {
  79.                 case en_autocon:
  80.                 case en_icon:
  81.                         fprintf(output,"%d",offset->v.i);
  82.                         if( echo )
  83.                             fprintf(stdout, "%d",offset->v.i);
  84.                         break;
  85.                 case en_labcon:
  86.                         fprintf(output,"L%04d",offset->v.i);
  87.                         if( echo ) fprintf(stdout,"L%04d",offset->v.i);
  88.                         break;
  89.                 case en_nacon:
  90.                         fprintf(output,"%s",offset->v.p[0]);
  91.                         if( echo ) fprintf(stdout,"%s",offset->v.p[0]);
  92.                         break;
  93.                 case en_add:
  94.                         putconst(offset->v.p[0]);
  95.                         fprintf(output,"+");
  96.                         if(echo) fprintf(stdout, "+");
  97.                         putconst(offset->v.p[1]);
  98.                         break;
  99.                 case en_sub:
  100.                         putconst(offset->v.p[0]);
  101.                         fprintf(output,"-");
  102.                         if( echo ) fprintf(stdout,"-");
  103.                         putconst(offset->v.p[1]);
  104.                         break;
  105.                 case en_uminus:
  106.                         fprintf(output,"-");
  107.                         if(echo) fprintf(stdout,"-");
  108.                         putconst(offset->v.p[0]);
  109.                         break;
  110.                 default:
  111.                         printf("DIAG - illegal constant node.\n");
  112.                         break;
  113.                 }
  114. }
  115.  
  116. putlen(l) /* append the length field to an instruction. */
  117. int     l;
  118. {       switch( l )
  119.                 {
  120.                 case 0:
  121.                         break;  /* no length field */
  122.                 case 1:
  123.                         fprintf(output,".b");
  124.                         if( echo ) fprintf(stdout,".b");
  125.                         break;
  126.                 case 2:
  127.                         fprintf(output,".w");
  128.                         if(echo) fprintf(stdout,".w");
  129.                         break;
  130.                 case 4:
  131.                         fprintf(output,".l");
  132.                         if(echo) fprintf(stdout,".l");
  133.                         break;
  134.                 default:
  135.                         printf("DIAG - illegal length field.\n");
  136.                         break;
  137.                 }
  138. }
  139.  
  140. putamode(ap) /* output a general addressing mode. */
  141. struct amode    *ap;
  142. {       switch( ap->mode )
  143.                 {
  144.                 case am_immed:
  145.                         fprintf(output,"#");
  146.                         if(echo) fprintf(stdout,"#");
  147.                 case am_direct:
  148.                         putconst(ap->offset);
  149.                         break;
  150.                 case am_areg:
  151.                         fprintf(output,"A%d",ap->preg);
  152.                         if( echo) fprintf(stdout,"A%d",ap->preg);
  153.                         break;
  154.                 case am_dreg:
  155.                         fprintf(output,"D%d",ap->preg);
  156.                         if(echo) fprintf(stdout,"D%d",ap->preg);
  157.                         break;
  158.                 case am_ind:
  159.                         fprintf(output,"(A%d)",ap->preg);
  160.                         if(echo) fprintf(stdout,"(A%d)",ap->preg);
  161.                         break;
  162.                 case am_ainc:
  163.                         fprintf(output,"(A%d)+",ap->preg);
  164.                         if(echo) fprintf(stdout,"(A%d)+",ap->preg);
  165.                         break;
  166.                 case am_adec:
  167.                         fprintf(output,"-(A%d)",ap->preg);
  168.                         if(echo) fprintf(stdout,"-(A%d)",ap->preg);
  169.                         break;
  170.                 case am_indx:
  171.                         putconst(ap->offset);
  172.                         fprintf(output,"(A%d)",ap->preg);
  173.                         if(echo) fprintf(stdout,"(A%d)",ap->preg);
  174.                         break;
  175.                 case am_xpc:
  176.                         putconst(ap->offset);
  177.                         fprintf(output,"(PC,D%d)",ap->preg);
  178.                         if(echo) fprintf(stdout,"(PC,D%d)",ap->preg);
  179.                         break;
  180.                 case am_indx2:
  181.                         putconst(ap->offset);
  182.                         fprintf(output,"(A%d,D%d.l)",ap->preg,ap->sreg);
  183.                         if(echo) fprintf(stdout,"(A%d,D%d.l)",ap->preg,ap->sreg);
  184.                         break;
  185.                 case am_indx3:
  186.                         putconst(ap->offset);
  187.                         fprintf(output,"(A%d,A%d.l)",ap->preg,ap->sreg);
  188.                         if(echo) fprintf(stdout,"(A%d,A%d.l)",ap->preg,ap->sreg);
  189.                         break;
  190.                 case am_mask:
  191.                         put_mask(ap->offset);
  192.                         break;
  193.                 default:
  194.                         printf("DIAG - illegal address mode.\n");
  195.                         break;
  196.                 }
  197. }
  198.  
  199. put_code(op,len,aps,apd) /* output a generic instruction. */
  200. struct amode    *aps, *apd;
  201. int             op, len;
  202. {       if( op == op_dc )
  203.         {
  204.         switch( len )
  205.             {
  206.             case 1: fprintf(output,"\tdc.b");
  207.                     if(echo) fprintf(stdout,"\tdc.b");
  208.                     break;
  209.             case 2: fprintf(output,"\tdc.w");
  210.                     if( echo ) fprintf(stdout,"\tdc.w");
  211.                     break;
  212.             case 4: fprintf(output,"\tdc.l");
  213.                     if( echo ) fprintf(stdout,"\tdc.l");
  214.                     break;
  215.             }
  216.         }
  217.     else
  218.         {
  219.         putop(op);
  220.             putlen(len);
  221.         }
  222.         if( aps != 0 )
  223.                 {
  224.                 fprintf(output,"\t");
  225.                 if(echo) fprintf(stdout,"\t");
  226.                 putamode( aps );
  227.                 if( apd != 0 )
  228.                 {
  229.                     fprintf(output,",");
  230.                     if(echo) fprintf(stdout,",");
  231.                     putamode( apd );
  232.                     }
  233.                 }
  234.         fprintf(output,"\n");
  235.         if(echo) fprintf(stdout,"\n");
  236. }
  237.  
  238. put_mask(mask)  /* generate a register mask for restore and save. */
  239. int     mask;
  240. {
  241.     unsigned int i, position = 15;
  242.     static int mswitch = 0;
  243.     char *reglist[] = { "A7","A6","A5","A4","A3","A2","A1","A0",
  244.                         "D7","D6","D5","D4","D3","D2","D1","D0" };
  245.     i = mask;
  246.     if( mswitch == 1) position = 0;
  247.     while( i >= 1 ) {
  248.         if( (i & 1) == 1 ) fprintf(output, "%s/", reglist[position]);
  249.         i = i >> 1;
  250.         if( mswitch == 1 ) position++; else position--;
  251.     }
  252.     if( mswitch == 1) mswitch = 0; else mswitch = 1;
  253. }
  254.  
  255. putreg(r) /* generate a register name from a tempref number. */
  256. int     r;
  257. {
  258.     if( r < 8 )
  259.     {
  260.         fprintf(output,"D%d",r);
  261.         if(echo) fprintf(stdout,"D%d",r);
  262.     }
  263.     else
  264.     {
  265.         fprintf(output,"A%d",r - 8);
  266.         if(echo) fprintf(stdout,"A%d",r-8);
  267.     }
  268. }
  269.  
  270. gen_strlab(s)  /* generate a named label. */
  271. char    *s;
  272. {
  273.     fprintf(output,"%s",s);
  274.     if( echo ) fprintf(stdout,"%s",s);
  275. }
  276.  
  277. put_label(lab)  /* output a compiler generated label. */
  278. int     lab;
  279. {
  280.     fprintf(output,"L%04d\n",lab);
  281.     if(echo) fprintf(stdout,"L%04d\n",lab);
  282. }
  283.  
  284. genbyte(val)
  285. int     val;
  286. {       if( gentype == bytegen && outcol < 30) {
  287.                 fprintf(output,",%d",val & 0x00ff);
  288.                 if(echo) fprintf(stdout,",%d",val & 0x00ff);
  289.                 outcol += 4;
  290.                 }
  291.         else    {
  292.                 nl();
  293.                 fprintf(output,"\tDC.B\t%d",val & 0x00ff);
  294.                 if( echo) fprintf(stdout,"\tDC.B\t%d",val & 0x00ff);
  295.                 gentype = bytegen;
  296.                 outcol = 19;
  297.                 }
  298. }
  299.  
  300. genword(val)
  301. int     val;
  302. {       if( gentype == wordgen && outcol < 29) {
  303.                 fprintf(output,",%d",val & 0x0ffff);
  304.                 if(echo) fprintf(stdout,",%d",val & 0x0ffff);
  305.                 outcol += 6;
  306.                 }
  307.         else    {
  308.                 nl();
  309.                 fprintf(output,"\tDC.W\t%d",val & 0x0ffff);
  310.                 if(echo) fprintf(stdout,"\tDC.W\t%d",val & 0x0ffff);
  311.                 gentype = wordgen;
  312.                 outcol = 21;
  313.                 }
  314. }
  315.  
  316. genlong(val)
  317. int     val;
  318. {       if( gentype == longgen && outcol < 28) {
  319.                 fprintf(output,",%d",val);
  320.                 if(echo) fprintf(stdout,",%d",val);
  321.                 outcol += 10;
  322.                 }
  323.         else    {
  324.                 nl();
  325.                 fprintf(output,"\tDC.L\t%d",val);
  326.                 if(echo) fprintf(stdout,"\tDC.L\t%d",val);
  327.                 gentype = longgen;
  328.                 outcol = 25;
  329.                 }
  330. }
  331.  
  332. genref(sp,offset)
  333. SYM     *sp;
  334. int     offset;
  335. {       char    sign;
  336.         if( offset < 0) {
  337.                 sign = '-';
  338.                 offset = -offset;
  339.                 }
  340.         else
  341.                 sign = '+';
  342.         if( gentype == longgen && outcol < 55 - strlen(sp->name)) {
  343.                 if( sp->storage_class == sc_static)
  344.                 {
  345.                     fprintf(output,",L%04d%c%d",sp->value.i,sign,offset);
  346.                     if(echo) fprintf(stdout,",L%04d%c%d",sp->value.i,sign,offset);
  347.                 }
  348.                 else
  349.                 {
  350.                         fprintf(output,",%s%c%d",sp->name,sign,offset);
  351.                         if(echo) fprintf(stdout,",%s%c%d",sp->name,sign,offset);
  352.                 }
  353.                 outcol += (11 + strlen(sp->name));
  354.                 }
  355.         else    {
  356.                 nl();
  357.                 if(sp->storage_class == sc_static)
  358.                 {
  359.                     fprintf(output,"\tlong\tL%04d%c%d",sp->value.i,sign,offset);
  360.                     if(echo) fprintf(stdout,"\tlong\tL%04d%c%d",sp->value.i,sign,offset);
  361.                 }
  362.                 else
  363.                 {
  364.                     fprintf(output,"\tlong\t%s%c%d",sp->name,sign,offset);
  365.                     if(echo) fprintf(stdout,"\tlong\t%s%c%d",sp->name,sign,offset);
  366.                 }
  367.                 outcol = 26 + strlen(sp->name);
  368.                 gentype = longgen;
  369.                 }
  370. }
  371.  
  372. genstorage(nbytes)
  373. int     nbytes;
  374. {       nl();
  375.         fprintf(output,"\tDS  \t%d\n",nbytes);
  376.         if(echo) fprintf(stdout,"\tDS  \t%d\n",nbytes);
  377. }
  378.  
  379. gen_labref(n)
  380. int     n;
  381. {       if( gentype == longgen && outcol < 58) {
  382.                 fprintf(output,",L%04d",n);
  383.                 if( echo ) fprintf(stdout,",L%04d",n);
  384.                 outcol += 6;
  385.                 }
  386.         else    {
  387.                 nl();
  388.                 fprintf(output,"\tlong\tL%04d",n);
  389.                 if(echo) fprintf(stdout,"\tlong\tL%04d",n);
  390.                 outcol = 22;
  391.                 gentype = longgen;
  392.                 }
  393. }
  394.  
  395. int  stringlit(s) /* make s a string literal and return it's label number. */
  396. char    *s;
  397. {       struct slit     *lp;
  398.         ++global_flag;          /* always allocate from global space. */
  399.         lp = xalloc(sizeof(struct slit));
  400.         lp->label = nextlabel++;
  401.         lp->str = litlate(s);
  402.         lp->next = strtab;
  403.         strtab = lp;
  404.         --global_flag;
  405.         return lp->label;
  406. }
  407.  
  408. dumplits() /* dump the string literal pool. */
  409. {       char            *cp;
  410.         while( strtab != 0) {
  411.                 cseg();
  412.                 nl();
  413.                 put_label(strtab->label);
  414.                 cp = strtab->str;
  415.                 while(*cp)
  416.                         genbyte(*cp++);
  417.                 genbyte(0);
  418.                 strtab = strtab->next;
  419.                 }
  420.         nl();
  421. }
  422.  
  423. nl()
  424. {       if(outcol > 0) {
  425.                 fprintf(output,"\n");
  426.                 if(echo) fprintf(stdout,"\n");
  427.                 outcol = 0;
  428.                 gentype = nogen;
  429.                 }
  430. }
  431.  
  432. cseg()
  433. {       if( curseg != codeseg) {
  434.                 nl();
  435.                 fprintf(output,"\n*\ttext\n");
  436.                 if(echo) fprintf(stdout,"\n*\ttext\n");
  437.                 curseg = codeseg;
  438.                 }
  439. }
  440.  
  441. dseg()
  442. {       if( curseg != dataseg) {
  443.                 nl();
  444.                 fprintf(output,"*\tdata\t2\n");
  445.                 if(echo) fprintf(stdout,"*\tdata\t2\n");
  446.                 curseg = dataseg;
  447.                 }
  448. }
  449.  
  450.