home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 148_01 / a99asmln.c < prev    next >
Text File  |  1987-09-28  |  11KB  |  499 lines

  1. /*
  2.     TMS9900/99105  Cross-Assembler  v. 1.0
  3.  
  4.     January, 1985
  5.  
  6.     Original 6800 version Copyright (c) 1980 William C. Colley, III.
  7.     Modified for the TMS9900/99105  Series by Alexander Cameron.
  8.  
  9. File:    a99asmln.c
  10.  
  11. Line assembly routine.
  12. */
  13.  
  14. /*  Get globals:  */
  15.  
  16. #include "a99.gbl"
  17.  
  18. /*
  19. This function is the workhorse of the assembler.  The routine
  20. gets any labels off the line and processes them, gets the opcode
  21. and builds the binary output as it evaluates the operand field.
  22. */
  23.  
  24. asmline()
  25. {
  26.     char c,label[2*SYMLEN], opattr;
  27.     unsigned opcode,op2;
  28.     nbytes = 0;
  29.     address = pc;
  30.     directok = TRUE;
  31.     evalerr = FALSE;
  32.     hexflg = NOCODE;
  33.     label[0] = '\0';
  34.     binbuf[0] = binbuf[2] = binbuf[4] = 0x10;
  35.     binbuf[1] = binbuf[3] = binbuf[5] = 0;        /* NOP = 0x1000  */
  36.     switch (getchr(&c,NOSKIP))
  37.     {
  38.         case ALPHA:    backchr;
  39.                 getname(label);
  40.                 if (chkoprat(label) != NO_OPR)
  41.                 {
  42.                     markerr('L');
  43.                     label[0] = '\0';
  44.                 }
  45.                 break;
  46.  
  47.         case END_LIN:    return;
  48.  
  49.         case BLANK:    break;
  50.  
  51.         default:    markerr('L');
  52.                 while((c = getchr(&c,NOSKIP)) != BLANK && c != END_LIN);
  53.                 backchr;
  54.     }
  55.     switch(getopcod(&opcode,&opattr))
  56.     {
  57.         case 0:        nbytes = 0;
  58.  
  59.         case -1:    opcode = 255;      /*  Set nil pseudo-op.    */
  60.                 opattr = 0x80;
  61.  
  62.         case 1:        if ((opattr & (PSOP | IFGROUP)) == (PSOP | IFGROUP))
  63.                 {
  64.                     if (label[0] != '\0') markerr('L');
  65.                 }
  66.                 else
  67.                 {
  68.                     if (ifstack[ifsp] == 0) return;
  69.                     if (label[0] != '\0')
  70.                     {
  71.                         strcat(label,PADDING);
  72.                         if (pass == 1)
  73.                         {
  74.                             if (addsym(label))
  75.                             {
  76.                                 sympoint -> symvalu = pc;
  77.                                 if ((opattr & PSOP) && opcode==0x000A)
  78.                                 {
  79.                                 sympoint -> symname[1] |= 0x80;
  80.                                 }
  81.                             }
  82.                         }
  83.                         else
  84.                         {
  85.                             if (slookup(label))
  86.                             {
  87.                                 markerr('P');
  88.                                 label[0] = '\0';
  89.                             }
  90.                             else
  91.                             {
  92.                                 if (sympoint -> symvalu != pc || (sympoint -> symname[1] & 0x80))
  93.                                 {
  94.                                     markerr('M');
  95.                                 }
  96.                                 sympoint -> symname[0] &= 0x7f;
  97.                             }
  98.                         }
  99.                     }
  100.                 }
  101.                 hexflg = PUTCODE;
  102.                 if (opattr & PSOP) _psop(opcode,label);
  103.                 else _normop(opcode,opattr);
  104.                 return;
  105.     }
  106. }
  107.  
  108. /*
  109. Internal function to process pseudo opcodes.
  110. */
  111.  
  112. _psop(opcode,label)
  113. char  *label;
  114. unsigned opcode; 
  115. {
  116.     char *bptr, c, d;
  117.     unsigned t,temp;
  118.     struct symbtbl *sptr;
  119.     sptr = sympoint;
  120.     bptr = binbuf;
  121.     switch (opcode)
  122.     {
  123.         case 0:        t = eval(START);        /* ORG.    */
  124.                 if (evalerr) return;
  125.                 address = pc = t;
  126.                 hexflg = FLUSH;
  127.                 if (label[0] == '\0') goto chkargs;
  128.                 backitem(t,VALUE);
  129.                 backchr;
  130.  
  131.         case 1:        if (label[0] == '\0')        /* EQU.    */
  132.                 {
  133.                     markerr('L');
  134.                     return;
  135.                 }
  136.                 if (!(sptr -> symname[1] & 0x80) && errcode == 'M')
  137.                 {
  138.                     errcode = ' ';
  139.                     errcount--;
  140.                 }
  141.                 t = eval(START);
  142.                 if (evalerr) return;
  143.                 address = sptr -> symvalu;
  144.                 sptr -> symvalu = t;
  145.                 if (!directok) markerr('P');
  146.                 if (address != t) markerr('M');
  147.                 goto chkargs;
  148.  
  149.         case 2:                        /* BYTE    */
  150.                 while ((c = getitem(&t,SMALST)) != END_LIN)
  151.                 {
  152.                     if (c == COMMA)
  153.                     {
  154.                         *bptr++ = 0;
  155.                         nbytes++; 
  156.                         continue;
  157.                     }
  158.                     backitem(t,c);
  159.                     t = eval(START);
  160.                 
  161.                     /* mod because eval now returns delimeter- gobbles up comma  */
  162.                     c=getitem(&temp,SMALST);
  163.                     if (evalerr || t > 0xff && t < 0xff80) markerr('V');
  164.                     *bptr++ = t;
  165.                     nbytes++;
  166.                     if(c==END_LIN) return;
  167.                 }
  168.                 return;
  169.  
  170.         case 3:                        /* WORD    */
  171.                 while ((c = getitem(&t,SMALST)) != END_LIN)
  172.                 {
  173.                     if (c == COMMA)
  174.                     {
  175.                         *bptr++ = 0;
  176.                         *bptr++ = 0;
  177.                         nbytes += 2;
  178.                         continue;
  179.                     }
  180.                     backitem(t,c);
  181.                     t=eval(START);
  182.                     c=getitem(&temp,SMALST);
  183.                     *bptr++ = t >> 8;
  184.                     *bptr++ = t;
  185.                     nbytes += 2;
  186.                     if(c==END_LIN) return;
  187.                 }
  188.                 return;
  189.  
  190.         case 4:                        /* TEXT    */
  191.                 while ((c = getchr(&d,SKIP)) != END_LIN)
  192.                 {
  193.                     if (c == COMMA) continue;
  194.                     if (c != QUOTE)
  195.                     {
  196.                         markerr('"');
  197.                         /*return;*/
  198.                     }
  199.                     while ((c = *linptr++) != d)
  200.                     {
  201.                         if (c == '\n')
  202.                         {
  203.                             markerr('"');
  204.                             return;
  205.                         }
  206.                         *bptr++ = c;
  207.                         nbytes++;
  208.                     }
  209.                 }
  210.                 return;
  211.  
  212.         case 5:        t = eval(START);        /* BSS    */
  213.             /*    if (evalerr) return;    */
  214.                 pc += t;
  215.                 hexflg = FLUSH;
  216.                 goto chkargs;
  217.  
  218.         case 6:        if (pass == 1) pass--;        /* END.    */
  219.                 else
  220.                 {
  221.                     pass++;
  222.                     if (ifsp != 0) markerr('I');
  223.                 }
  224.                 hexflg = NOMORE;
  225.                 goto chkargs;
  226.  
  227.         case 7:                    /*  ELSE.    */
  228.         case 8:        hexflg = NOCODE;    /*  ENDI.    */
  229.                 if (ifsp == 0)
  230.                 {
  231.                     markerr('I');
  232.                     return;
  233.                 }
  234.                 if (opcode == 8) ifsp--;
  235.                 else ifstack[ifsp] = ~ifstack[ifsp];
  236.                 goto chkargs;
  237.  
  238.         case 9:        t = eval(START);        /* IF.    */
  239.                 if (evalerr || !directok)
  240.                 {
  241.                     markerr('P');
  242.                     t = 0xffff;
  243.                 }
  244.                 if (ifsp == 16) wipeout("\nIf stack overflow.\n");
  245.                 ifstack[++ifsp] = address = t;
  246.                 goto chkargs;
  247.  
  248.         case 10:    if (label[0] == '\0')        /* SET.    */
  249.                 {
  250.                     markerr('L');
  251.                     return;
  252.                 }
  253.                 if ((sptr -> symname[1] & 0x80) && errcode == 'M')
  254.                 {
  255.                     errcode = ' ';
  256.                     errcount--;
  257.                 }
  258.                 t = eval(START);
  259.                 if (evalerr) return;
  260.                 address = sptr -> symvalu = t;
  261.                 if (!directok) markerr('P');
  262.                 goto chkargs;
  263.  
  264.         case 11:    if(pc & 1)            /* EVEN */
  265.                 {    nbytes++;
  266.                     *bptr=0;
  267.                 }
  268.                 goto chkargs;
  269.  
  270.         case 12:    hexflg=NOCODE;            /* DXOP */
  271.                 if(getchr(&c,SKIP) != ALPHA)    
  272.                 {
  273.                     markerr('S');
  274.                     return;
  275.                 }
  276.                 backchr;
  277.                 getname(label);        /* name of DXOP */
  278.                 strcat(label,PADDING);
  279.                 getitem(&t,SMALST);    /* skip to number */
  280.                 t=eval(START);        /* DXOP number */
  281.                 if(evalerr || t >15)
  282.                 {
  283.                     markerr('S');
  284.                     return;
  285.                 }
  286.                 if( pass == 1)
  287.                     if(addsym(label)) sympoint ->symvalu = ( 0x2C00 | t << 6 );    /* XOP opcode */
  288.                                 
  289.                 return;
  290.  
  291.         chkargs:    if (getitem(&c,SMALST) != END_LIN) markerr('T');
  292.                 return;
  293.  
  294.         case 255:                /*  NO OPCODE.    */
  295.                 if (nbytes == 0) hexflg = NOCODE;
  296.                 return;
  297.     }
  298. }
  299.  
  300. /*
  301. Internal function to process normal (non-pseudo) opcodes.
  302. */
  303.  
  304. _normop(opcode,attr)
  305. unsigned opcode;
  306. char attr;
  307. {
  308.     unsigned regmask,regval,t,operand,value;
  309.     int disp;
  310.     char shift,c,parse,opdcount,attr1,attr2;
  311.     nbytes = 2;
  312.     if(pc & 1){ pc++; address++; }     /* make sure code is on an even boundary */
  313.     operand=0;
  314.     attr1=attr & 0x07;       /*  mask 3 most least significant bits */
  315.     attr2=(attr & 0x38) >> 3;   /* next 3 bits represent attr2 */ 
  316.     attr=attr1;
  317.     opdcount=1;
  318.     while(TRUE)
  319.     {    parse=TRUE;
  320.         addrmode=WREG;     /* default address mode */
  321.         switch(attr)
  322.         {
  323.  
  324.             case 0:    if(attr1 || attr2) markerr('S');
  325.                 binbuf[0] = opcode >> 8;
  326.                 binbuf[1] = opcode;
  327.                 if(c=getitem(&value,SMALST) != END_LIN) markerr('T');
  328.                 return; 
  329.  
  330.             /* Format 1 - S,D  */
  331.             /* detect N,*N,*N+,@X,@X(N) */
  332.  
  333.             case 1:    while(parse)
  334.                 {
  335.                 switch(c=getitem(&value,SMALST))
  336.                 {
  337.                             
  338.                     case OPERATR:    if(value=='*')addrmode=INDIRECT;
  339.                             if(value=='@')
  340.                                 {
  341.                                 addrmode=SYMBOLIC;
  342.                                 nbytes += 2;
  343.  
  344.                                 }
  345.                             break;
  346.  
  347.                     case VALUE :    regval = 0;
  348.                             backitem(value,c);
  349.                             t=eval(START);
  350.                             if(evalerr) markerr('S');
  351.                             switch(addrmode)
  352.                             {
  353.                                 case WREG:    regval=t;regmask=0;break;
  354.                                 case INDIRECT:    regval=t;regmask=1;break;
  355.                                 case AUTOINC:    regval=t;regmask=3;break;
  356.                                 case SYMBOLIC:    regmask=2;
  357.                                         binbuf[nbytes - 2] = t>>8;
  358.                                         binbuf[nbytes - 1] = t;
  359.                                         break;
  360.                                 case INDEXED:    regmask=2;
  361.                                         binbuf[nbytes - 2] = t >> 8;
  362.                                         binbuf[nbytes - 1] = t;
  363.                                         regval=eval(START);
  364.                                         if(evalerr) markerr('E');
  365.                             }
  366.                             if(regval > 15) markerr('R');
  367.  
  368.                             if(opdcount == 2) shift=6;
  369.                                 else shift=0;
  370.                             operand |= (regval << shift);
  371.                             operand |= (regmask << shift + 4);
  372.                             break;
  373.  
  374.                     case COMMA:    opdcount++;
  375.                             if(opdcount > 3) {markerr('T'); break;}
  376.                             attr=attr2;
  377.                             parse=FALSE;
  378.                             break;
  379.  
  380.                     case END_LIN:    opcode |= operand;
  381.                             binbuf[0]=opcode>>8;
  382.                             binbuf[1]=opcode;
  383.                             return;    
  384.                 }    
  385.                 }
  386.                 break;
  387.                 
  388.         /*  case 2 handles signed displacement */
  389.  
  390.         case 2:    while(TRUE)
  391.             {    switch(c=getitem(&value,SMALST))
  392.                     {
  393.                     case OPERATR:
  394.                     case VALUE:    backitem(value,c);
  395.                             operand=eval(START);
  396.                             break;
  397.     
  398.                     case END_LIN:    operand -=pc+2;
  399.                             disp=operand/2;
  400.                             if(disp > 127 && disp > -128) markerr('B');
  401.                             opcode |= disp & 0xff;
  402.                             binbuf[0]=opcode>>8;
  403.                             binbuf[1]=opcode;
  404.                             return;
  405.                     
  406.                     default:    markerr('S');
  407.                     }    
  408.             }
  409.  
  410.         /*  Destination register only - D and also C   */
  411.  
  412.         case 3:    regval = eval(START);
  413.             if( evalerr) markerr('S');
  414.             if( regval > 15 ) markerr('R');
  415.             if( getitem(&value,SMALST) != END_LIN) markerr('T');
  416.             if(opdcount != 2) markerr('S');
  417.             operand |= regval << 6;
  418.             opcode |= operand;
  419.             binbuf[0]=opcode>>8;
  420.             binbuf[1]=opcode;
  421.             return;
  422.  
  423.  
  424.         /*  Bit field operands    */
  425.  
  426.         case 4: disp=eval(START);
  427.             if(evalerr) markerr('S');
  428.             opcode |= disp & 0xff;
  429.             binbuf[0] = opcode >> 8;
  430.             binbuf[1] = opcode;
  431.             if(getitem(&value,SMALST) != END_LIN) markerr('T');
  432.             return;
  433.  
  434.         /*  Workspace register - W  or shift count C  */
  435.  
  436.         case 5:    while(parse)
  437.             {
  438.             switch(c=getitem(&value,SMALST))
  439.             {
  440.                 case VALUE:
  441.                 case OPERATR:    backitem(value,c);
  442.                         regval=eval(START);
  443.                         if(regval > 15 ) markerr('R');
  444.                         if(opdcount == 2) operand |= regval << 4;
  445.                             else operand = regval;
  446.                         break;
  447.  
  448.                 case COMMA:    opdcount++;
  449.                         if(opdcount > 3) {markerr('T'); break;}
  450.                         parse = FALSE;
  451.                         attr=attr2;
  452.                         break;
  453.  
  454.  
  455.                 case END_LIN:    opcode |= operand;
  456.                         binbuf[0] = opcode >> 8;
  457.                         binbuf[1] = opcode;
  458.                         return;
  459.  
  460.             }
  461.             }
  462.             break;
  463.  
  464.         /*  Immediate operation - IOP */
  465.  
  466.         case 6: nbytes += 2;
  467.             t = eval(START);
  468.             opcode |= operand;
  469.             binbuf[0] = opcode >> 8;
  470.             binbuf[1] = opcode;
  471.             binbuf[2] = t >> 8;
  472.             binbuf[3] = t;
  473.             if(getitem(&value,SMALST) != END_LIN) markerr('T');
  474.             return;
  475.  
  476.         /* Bit Manipulation Instructions - for the 99105 only 
  477.            this instruction has a very similar format to the CRU
  478.            Bit Manipulation set and but the opcode addressing modes
  479.            are in the second word i.e.    [     opcode     ]
  480.                             [ format3|format1]
  481.            hence calling _normop recursively we can then easily
  482.            swap the words around to produce the correct code   */
  483.  
  484.         case 7: _normop(0x0000,0x19);    /* call with opcode 0 and format 3 and format 1  */
  485.             nbytes += 2;        /* binbuf[0,1,2,3] now hold the 2nd and 3rd word */
  486.             binbuf[4] = binbuf[2];  /* shift data down by 1 word to */
  487.             binbuf[5] = binbuf[3];  /* allow for opcode             */
  488.             binbuf[2] = binbuf[0];
  489.             binbuf[3] = binbuf[1];
  490.             binbuf[0] = opcode >> 8; /* now place original opcode in 1st word  */
  491.             binbuf[1] = opcode;
  492.             return;
  493.  
  494.         default: wipeout("bad operand format -- aborting \n");
  495.             exit();
  496.         }
  497.     }
  498. }
  499.