home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 363_01 / assemble.c < prev    next >
C/C++ Source or Header  |  1991-09-24  |  13KB  |  336 lines

  1. /***********************************************************************
  2.  *
  3.  *      ASSEMBLE.C
  4.  *      Assembly Routines for 68020 Assembler
  5.  *
  6.  *    Function: processFile()
  7.  *      Assembles the input file. For each pass, the function passes each line 
  8.  *      of the input file to assemble() to be assembled. The routine also makes
  9.  *      sure that errors are printed on the screen and listed in the listing 
  10.  *      file and keeps track of the error counts and the line number.
  11.  *
  12.  *      assemble()
  13.  *      Assembles one line of assembly code. The line argument points to the 
  14.  *      line to be assembled, and the errorPtr argument is used to return an 
  15.  *      error code via the standard mechanism. The routine first determines if 
  16.  *      the line contains a label and saves the label for later use. It then 
  17.  *      calls instLookup() to look up the instruction (or directive) in the 
  18.  *      instruction table. If this search is successful and the parseFlag for 
  19.  *      that instruction is TRUE, it defines the label and parses the source 
  20.  *      and destination operands of the instruction (if appropriate) and 
  21.  *      searches the variant list for the instruction, calling the proper 
  22.  *      routine if a match is found. If parseFlag is FALSE, it passes pointers 
  23.  *      to the label and operands to the specified routine for processing.
  24.  *
  25.  *   Usage: processFile()
  26.  *
  27.  *      assemble(char *line, int *errorPtr)
  28.  *
  29.  *      Author: Paul McKee
  30.  *      ECE492    North Carolina State University, 12/13/86
  31.  *
  32.  *      Modified: A.E.Romer, 1991. Version 1.0
  33.  *
  34.  *      Question: What is 'return NORMAL' for? Nothing ever checks it.
  35.  *
  36.  ************************************************************************/
  37.  
  38.  
  39. #include <stdio.h>
  40. #include <ctype.h>
  41. #include "asm.h"
  42.  
  43.  
  44. #define     SKIPSPACE(ptr)      while (isspace(*ptr)) ptr++
  45. #define     SKIPNONSPACE(ptr)   while (!isspace(*ptr)) ptr++
  46.  
  47.  
  48. extern long loc;                        /* The assembler's location counter */
  49. extern char pass2;                           /* Flag set during second pass */
  50. extern char endFlag;      /* Flag set when the END directive is encountered */
  51. extern char continuation;     /* TRUE if the listing line is a continuation
  52.                                * (used by 'listing.c')                      */
  53. extern char noOperand;        /* TRUE if the instruction has no operand.
  54.                                * Used by listLine. */
  55.  
  56. extern int lineNum;
  57. extern int errorCount, warningCount;
  58.  
  59. extern char line[LBUF_SIZE];        /* Source line */
  60. extern FILE *inFile;                /* Input file */
  61. extern FILE *listFile;              /* Listing file */
  62. extern char listFlag;
  63.  
  64.  
  65.  
  66. int pickMask(int size, variant *variantPtr, int *errorPtr)
  67.     {
  68.     if (!size || size & variantPtr->sizes)
  69.         if (size & (BYTE | SHORT))
  70.             return variantPtr->bytemask;
  71.         else if (!size || size == WORD)
  72.             return variantPtr->wordmask;
  73.         else
  74.             return variantPtr->longmask;
  75.     NEWERROR(*errorPtr, INV_SIZE_CODE);
  76.     return variantPtr->wordmask;
  77.     }
  78.  
  79.  
  80. int strcap(char *d, char *s)
  81.                             /* convert s into capitals in d, except characters
  82.                              * delimited by CHAR_DELIMITER
  83.                              */
  84.     {
  85.     char capFlag;
  86.  
  87.     capFlag = TRUE;
  88.     while (*s)
  89.         {
  90.         if (capFlag)
  91.             *d = toupper(*s);
  92.         else
  93.             *d = *s;
  94.         if (*s == CHAR_DELIMITER)
  95.             capFlag = (char) !capFlag;
  96.         d++;
  97.         s++;
  98.         }
  99.     *d = '\0';
  100.  
  101.     return NORMAL;
  102.     }
  103.  
  104.  
  105. int processFile(void)
  106.     {
  107.     char capLine[256];
  108.     int error;
  109.     char pass;
  110.  
  111.     hashInit();                        /* initialize hash table for symbols */
  112.  
  113.     pass2 = FALSE;
  114.     for (pass = 0; pass < 2; pass++)
  115.         {
  116.         loc = 0;
  117.         lineNum = 1;
  118.         endFlag = FALSE;
  119.         errorCount = warningCount = 0;
  120.         while(!endFlag && fgets(line, LBUF_SIZE, inFile))
  121.                     /* read up to (LBUF_SIZE - 1) characters, append '\0' */
  122.             {
  123.             strcap(capLine, line);              /* convert to capitals,
  124.                                                  * except quoted characters */
  125.             error = OK;
  126.             continuation = FALSE;
  127.             if (pass2 && listFlag)
  128.                 listLoc();                  /* insert program counter value
  129.                                              * in the listing line */
  130.             assemble(capLine, &error);
  131.             if (pass2)
  132.                 {
  133.                 if (error > MINOR)
  134.                     errorCount++;
  135.                 else if (error > WARNING)
  136.                     warningCount++;
  137.                 if (listFlag)
  138.                     {
  139.                     listLine();             /* complete listing line */
  140.                     printError(listFile, error, -1);
  141.                     }
  142.                 printError(stderr, error, lineNum);
  143.                 }
  144.             lineNum++;
  145.             }
  146.         if (!pass2)
  147.             {
  148.             pass2 = TRUE;
  149.             puts("Pass 2");
  150.             }
  151.         rewind(inFile);
  152.         }
  153.     return NORMAL;
  154.     }
  155.  
  156. int assemble(char *line, int *errorPtr)
  157.     {
  158.     instruction *tablePtr;
  159.     variant *variantPtr;
  160.     opDescriptor source, dest;
  161.     char label[SIGCHARS+1], size, v, sourceParsed, destParsed;
  162.     unsigned short mask, i;
  163.  
  164.  
  165.     label[0] = '\0';                             /* initialize label buffer */
  166.     noOperand = FALSE;              /* Most instructions have operands. Those
  167.                                      * that do not will have noOperand set to
  168.                                      * TRUE ('zeroOp' in build.c, trapcc.c */
  169.  
  170.     if (*line == '\n' || *line == '*')
  171.         return NORMAL;              /* ignore empty lines and comment lines */
  172.  
  173.     if (!isspace(*line))
  174.         if (isalpha(*line) || *line == '_' || *line == '.')
  175.                                     /* valid for first character of a label */
  176.             {
  177.             label[0] = line[0];
  178.             for (i = 1; (!isspace(line[i]) && line[i] != ':'); i++)
  179.                 {
  180.                 if (i < SIGCHARS)
  181.                     label[i] = line[i];
  182.                 if (!isalnum(line[i]) && line[i] != '_')
  183.                           /* not valid for subsequent character of a label */
  184.                     NEWERROR(*errorPtr, INV_LABEL);
  185.                 }
  186.             label[i] = '\0';
  187.             line += i;
  188.             if (*line == ':')
  189.                 line += 1;                        /* skip label terminator */
  190.  
  191. /* Create label only if nothing else on line, otherwise the label will be
  192.  * created when the instruction is parsed, to allow for labels defined by
  193.  * directives */
  194.  
  195.             SKIPSPACE(line);
  196.             if (*line == '*' || *line == '\0')       /* label only on line */
  197.                 {
  198.                         /* Move location counter to a word boundary and
  199.                            fix the listing before creating a label */
  200.                 if (loc & 1)                    /* if not at word boundary */
  201.                     {
  202.                     loc++;
  203.                     listLoc();
  204.                     }
  205.                 create(label, loc, errorPtr);
  206.                 return NORMAL;
  207.                 }
  208.             }
  209.         else
  210.             {
  211.             NEWERROR(*errorPtr, INV_LABEL);
  212.             SKIPNONSPACE(line);                     /* skip invalid label */
  213.             }
  214.  
  215.     SKIPSPACE(line);
  216.  
  217.     if (*line == '\0' || *line == '*')
  218.         return NORMAL;              /* ignore empty lines and comment lines */
  219.  
  220. /* p now points to the first character of the instruction field */
  221.     line = instLookup(line, &tablePtr, &size, errorPtr);
  222.                                                     /* identify instruction */
  223.     if (*errorPtr > SEVERE)
  224.         return NORMAL;
  225.     SKIPSPACE(line);
  226.  
  227. /* Case 1: instruction can be processed by 'assemble' */
  228.  
  229.     if (tablePtr->parseFlag)
  230.         {
  231.                         /* Move location counter to a word boundary and fix
  232.                            the listing before assembling an instruction */
  233.         if (loc & 1)                         /* if not at word boundary */
  234.             {
  235.             loc++;
  236.             listLoc();
  237.             }
  238.         if (*label)
  239.             {
  240.             create(label, loc, errorPtr);
  241.             if (*errorPtr > SEVERE)
  242.                 return NORMAL;
  243.             }
  244.  
  245.         sourceParsed = destParsed = FALSE;        /* nothing parsed yet */
  246.         variantPtr = tablePtr->variantPtr;
  247.         for (v = 0; v < tablePtr->variantCount; v++, variantPtr++)
  248.                                      /* for each variant of the instruction */
  249.             {
  250. /* Parse source only if required for this variant, but not parsed yet */
  251.             if (!sourceParsed && variantPtr->source)
  252.                 {
  253.                 line = opParse(line, &source, errorPtr);
  254.                 if (*errorPtr > SEVERE)
  255.                     return NORMAL;
  256.                 sourceParsed = TRUE;
  257.                                     /* ensure source parsed once only */
  258.                 }
  259. /* Parse destination only if required for this variant, but not parsed yet */
  260.             if (!destParsed && variantPtr->dest)
  261.                 {
  262.                 if (*line != ',')
  263.                                     /* missing source/destination separator */
  264.                     {
  265.                     NEWERROR(*errorPtr, SYNTAX);
  266.                     return NORMAL;
  267.                     }
  268.                 line = opParse(line+1, &dest, errorPtr);
  269.                 if (*errorPtr > SEVERE)
  270.                     return NORMAL;
  271.                 if (!isspace(*line) && *line != '\0')
  272.                                         /* if operand field contains
  273.                                          * superfluous characters */
  274.                     {
  275.                     NEWERROR(*errorPtr, SYNTAX);
  276.                     return NORMAL;
  277.                     }
  278.                 destParsed = TRUE;
  279.                                     /* ensure destination parsed once only */
  280.                 }
  281. /* Source not required, therefore destination not required either */
  282.  
  283.             if (variantPtr->source == 0)
  284.                 {
  285.                 mask = pickMask( (int) size, variantPtr, errorPtr);
  286.                                                     /* get size mask */
  287.                 (*variantPtr->exec)(mask, (int) size,
  288.                                                     &source, &dest, errorPtr);
  289.                                                         /* build code */
  290.                 return NORMAL;
  291.                 }
  292.  
  293. /* Source required, destination not required */
  294.  
  295.             else if ((source.mode & variantPtr->source)
  296.                                                         && !variantPtr->dest)
  297.                                         /* If source address mode is as
  298.                                          * required for this variant */
  299.                 {
  300.                 if (!isspace(*line) && *line != '\0')
  301.                                         /* if superfluous characters follow */
  302.                     {
  303.                     NEWERROR(*errorPtr, SYNTAX);
  304.                     return NORMAL;
  305.                     }
  306.                 mask = pickMask( (int) size, variantPtr, errorPtr);
  307.                 (*variantPtr->exec)(mask, (int) size,
  308.                                                 &source, &dest, errorPtr);
  309.                 return NORMAL;
  310.                 }
  311.  
  312. /* Both source and destination required */
  313.  
  314.             else if (source.mode & variantPtr->source
  315.                                 && dest.mode & variantPtr->dest)
  316.                                              /* If both are as required for
  317.                                               * this variant */
  318.                 {
  319.                 mask = pickMask( (int) size, variantPtr, errorPtr);
  320.                 (*variantPtr->exec)(mask, (int) size,
  321.                                                     &source, &dest, errorPtr);
  322.                 return NORMAL;
  323.                 }
  324.             }
  325.         NEWERROR(*errorPtr, INV_ADDR_MODE);
  326.         }
  327.  
  328. /* Case 2: instruction can't be processed by 'assemble' */
  329.  
  330.     else
  331.         {
  332.         (*tablePtr->exec)(tablePtr, (int) size, label, line, errorPtr);
  333.         return NORMAL;
  334.         }
  335.      }
  336.