home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / CROSSASM / 68ASMSIM.ZIP / asmsrc / opparse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-09-08  |  8.8 KB  |  348 lines

  1. /***********************************************************************
  2.  *
  3.  *        OPPARSE.C
  4.  *        Operand Parser for 68000 Assembler
  5.  *
  6.  *    Function: opParse()
  7.  *        Parses an operand of the 68000 assembly language
  8.  *        instruction and attempts to recognize its addressing
  9.  *        mode. The p argument points to the string to be
  10.  *        evaluated, and the function returns a pointer to the
  11.  *        first character beyond the end of the operand.
  12.  *        The function returns a description of the operands that
  13.  *        it parses in an opDescriptor structure. The fields of
  14.  *        the operand descriptor are filled in as appropriate for
  15.  *        the mode of the operand that was found:
  16.  *
  17.  *         mode      returns the address mode (symbolic values
  18.  *               defined in ASM.H)
  19.  *         reg       returns the address or data register number 
  20.  *         data      returns the displacement or address or
  21.  *               immediate value
  22.  *         backRef   TRUE if data is the value of an expression
  23.  *               that contains only constants and backwards
  24.  *               references; FALSE otherwise.
  25.  *         index     returns the index register
  26.  *               (0-7 = D0-D7, 8-15 = A0-A7)
  27.  *         size      returns the size to be used for the index
  28.  *               register
  29.  *
  30.  *        The argument errorPtr is used to return an error code
  31.  *        via the standard mechanism. 
  32.  *
  33.  *     Usage:    char *opParse(p, d, errorPtr)
  34.  *        char *p;
  35.  *        opDescriptor *d;
  36.  *        int *errorPtr;
  37.  *
  38.  *      Author: Paul McKee
  39.  *        ECE492    North Carolina State University
  40.  *
  41.  *        Date: 10/10/86
  42.  *
  43.  *    Revision: 10/26/87
  44.  *        Altered the immediate mode case to correctly flag
  45.  *        constructs such as "#$1000(A5)" as syntax errors. 
  46.  *
  47.  ************************************************************************/
  48.  
  49.  
  50. #include <stdio.h>
  51. #include <ctype.h>
  52. #include "asm.h"
  53.  
  54.  
  55. extern char pass2;
  56.  
  57.  
  58. #define isTerm(c)   (isspace(c) || (c == ',') || c == '\0')
  59. #define isRegNum(c) ((c >= '0') && (c <= '7'))
  60.  
  61. char *opParse(p, d, errorPtr)
  62. char *p;
  63. opDescriptor *d;
  64. int *errorPtr;
  65. {
  66.  
  67.     /* Check for immediate mode */
  68.     if (p[0] == '#') {
  69.         p = eval(++p, &(d->data), &(d->backRef), errorPtr);
  70.         /* If expression evaluates OK, then return */
  71.         if (*errorPtr < SEVERE) {
  72.             if (isTerm(*p)) {
  73.                 d->mode = Immediate;
  74.                 return p;
  75.                 }
  76.             else {
  77.                 NEWERROR(*errorPtr, SYNTAX);
  78.                 return NULL;
  79.                 }
  80.             }
  81.         else
  82.             return NULL;
  83.         }
  84.     /* Check for address or data register direct */
  85.     if (isRegNum(p[1]) && isTerm(p[2])) {
  86.         if (p[0] == 'D') {
  87.             d->mode = DnDirect;
  88.             d->reg = p[1] - '0';
  89.             return (p + 2);
  90.             }
  91.         else if (p[0] == 'A') {
  92.             d->mode = AnDirect;
  93.             d->reg = p[1] - '0';
  94.             return (p + 2);
  95.             }
  96.         }
  97.     /* Check for Stack Pointer (i.e., A7) direct */
  98.     if (p[0] == 'S' && p[1] == 'P' && isTerm(p[2])) {
  99.         d->mode = AnDirect;
  100.         d->reg = 7;
  101.         return (p + 2);
  102.         }
  103.     /* Check for address register indirect */
  104.     if (p[0] == '(' && 
  105.         ((p[1] == 'A' && isRegNum(p[2])) || (p[1] == 'S' && p[2] == 'P'))) {
  106.  
  107.         if (p[1] == 'S')
  108.             d->reg = 7;
  109.         else 
  110.             d->reg = p[2] - '0';
  111.         if (p[3] == ')') {
  112.             /* Check for plain address register indirect */
  113.             if (isTerm(p[4])) {
  114.                 d->mode = AnInd;
  115.                 return p+4;
  116.                 }
  117.             /* Check for postincrement */
  118.             else if (p[4] == '+') {
  119.                 d->mode = AnIndPost;
  120.                 return p+5;
  121.                 }
  122.             }
  123.         /* Check for address register indirect with index */
  124.         else if (p[3] == ',' && (p[4] == 'A' || p[4] == 'D')
  125.              && isRegNum(p[5])) {
  126.             d->mode = AnIndIndex;
  127.             /* Displacement is zero */
  128.             d->data = 0;
  129.             d->backRef = TRUE;
  130.             d->index = p[5] - '0';
  131.             if (p[4] == 'A')
  132.                 d->index += 8;
  133.             if (p[6] == '.')
  134.                 /* Determine size of index register */
  135.                 if (p[7] == 'W') {
  136.                     d->size = WORD;
  137.                     return p+9;
  138.                     }
  139.                 else if (p[7] == 'L') {
  140.                     d->size = LONG;
  141.                     return p+9;
  142.                     }
  143.                 else {
  144.                     NEWERROR(*errorPtr, SYNTAX);
  145.                     return NULL;
  146.                     }
  147.             else if (p[6] == ')') {
  148.                 /* Default index register size is Word */
  149.                 d->size = WORD;
  150.                 return p+7;
  151.                 }
  152.             else {
  153.                 NEWERROR(*errorPtr, SYNTAX);
  154.                 return NULL;
  155.                 }
  156.             }
  157.         }
  158.     /* Check for address register indirect with predecrement */
  159.     if (p[0] == '-' && p[1] == '(' && p[4] == ')' &&
  160.         ((p[2] == 'A' && isRegNum(p[3])) || (p[2] == 'S' && p[3] == 'P'))) {
  161.  
  162.         if (p[2] == 'S')
  163.             d->reg = 7;
  164.         else 
  165.             d->reg = p[3] - '0';
  166.         d->mode = AnIndPre;
  167.         return p+5;
  168.         }
  169.     /* Check for PC relative */
  170.     if (p[0] == '(' && p[1] == 'P' && p[2] == 'C') {
  171.         /* Displacement is zero */
  172.         d->data = 0;
  173.         d->backRef = TRUE;
  174.         /* Check for plain PC relative */
  175.         if (p[3] == ')') {
  176.             d->mode = PCDisp;
  177.             return p+4;
  178.             }
  179.         /* Check for PC relative with index */
  180.         else if (p[3] == ',' && (p[4] == 'A' || p[4] == 'D')
  181.              && isRegNum(p[5])) {
  182.             d->mode = PCIndex;
  183.             d->index = p[5] - '0';
  184.             if (p[4] == 'A')
  185.                 d->index += 8;
  186.             if (p[6] == '.')
  187.                 /* Determine size of index register */
  188.                 if (p[7] == 'W') {
  189.                     d->size = WORD;
  190.                     return p+9;
  191.                     }
  192.                 else if (p[7] == 'L') {
  193.                     d->size = LONG;
  194.                     return p+9;
  195.                     }
  196.                 else {
  197.                     NEWERROR(*errorPtr, SYNTAX);
  198.                     return NULL;
  199.                     }
  200.             else if (p[6] == ')') {
  201.                 /* Default size of index register is Word */
  202.                 d->size = WORD;
  203.                 return p+7;
  204.                 }
  205.             else {
  206.                 NEWERROR(*errorPtr, SYNTAX);
  207.                 return NULL;
  208.                 }
  209.             }
  210.         }
  211.  
  212.     /* Check for Status Register direct */
  213.     if (p[0] == 'S' && p[1] == 'R' && isTerm(p[2])) {
  214.         d->mode = SRDirect;
  215.         return p+2;
  216.         }    
  217.     /* Check for Condition Code Register direct */
  218.     if (p[0] == 'C' && p[1] == 'C' && p[2] == 'R' && isTerm(p[3])) {
  219.         d->mode = CCRDirect;
  220.         return p+3;
  221.         }
  222.     /* Check for User Stack Pointer direct */
  223.     if (p[0] == 'U' && p[1] == 'S' && p[2] == 'P' && isTerm(p[3])) {
  224.         d->mode = USPDirect;
  225.         return p+3;
  226.         }    
  227.     /* Check for Source Function Code register direct (68010) */
  228.     if (p[0] == 'S' && p[1] == 'F' && p[2] == 'C' && isTerm(p[3])) {
  229.         d->mode = SFCDirect;
  230.         return p+3;
  231.         }    
  232.     /* Check for Destination Function Code register direct (68010) */
  233.     if (p[0] == 'D' && p[1] == 'F' && p[2] == 'C' && isTerm(p[3])) {
  234.         d->mode = DFCDirect;
  235.         return p+3;
  236.         }    
  237.     /* Check for Vector Base Register direct (68010) */
  238.     if (p[0] == 'V' && p[1] == 'B' && p[2] == 'R' && isTerm(p[3])) {
  239.         d->mode = VBRDirect;
  240.         return p+3;
  241.         }    
  242.  
  243.     /* All other addressing modes start with a constant expression */
  244.     p = eval(p, &(d->data), &(d->backRef), errorPtr);
  245.     if (*errorPtr < SEVERE) {
  246.         /* Check for absolute */
  247.         if (isTerm(p[0])) {
  248.             /* Determine size of absolute address (must be long if
  249.                the symbol isn't defined or if the value is too big */
  250.             if (!d->backRef || d->data > 32767 || d->data < -32768)
  251.                 d->mode = AbsLong;
  252.             else
  253.                 d->mode = AbsShort;
  254.             return p;
  255.             }
  256.         /* Check for address register indirect with displacement */
  257.         if (p[0] == '(' && 
  258.             ((p[1] == 'A' && isRegNum(p[2])) || (p[1] == 'S' && p[2] == 'P'))) {
  259.             if (p[1] == 'S')
  260.                 d->reg = 7;
  261.             else 
  262.                 d->reg = p[2] - '0';
  263.             /* Check for plain address register indirect with displacement */
  264.             if (p[3] == ')') {
  265.                 d->mode = AnIndDisp;
  266.                 return p+4;
  267.                 }
  268.             /* Check for address register indirect with index */
  269.             else if (p[3] == ',' && (p[4] == 'A' || p[4] == 'D')
  270.                  && isRegNum(p[5])) {
  271.                 d->mode = AnIndIndex;
  272.                 d->index = p[5] - '0';
  273.                 if (p[4] == 'A')
  274.                     d->index += 8;
  275.                 if (p[6] == '.')
  276.                     /* Determine size of index register */
  277.                     if (p[7] == 'W') {
  278.                         d->size = WORD;
  279.                         return p+9;
  280.                         }
  281.                     else if (p[7] == 'L') {
  282.                         d->size = LONG;
  283.                         return p+9;
  284.                         }
  285.                     else {
  286.                         NEWERROR(*errorPtr, SYNTAX);
  287.                         return NULL;
  288.                         }
  289.                 else if (p[6] == ')') {
  290.                     /* Default size of index register is Word */
  291.                     d->size = WORD;
  292.                     return p+7;
  293.                     }
  294.                 else {
  295.                     NEWERROR(*errorPtr, SYNTAX);
  296.                     return NULL;
  297.                     }
  298.                 }
  299.             }
  300.         
  301.         /* Check for PC relative */
  302.         if (p[0] == '(' && p[1] == 'P' && p[2] == 'C') {
  303.             /* Check for plain PC relative */
  304.             if (p[3] == ')') {
  305.                 d->mode = PCDisp;
  306.                 return p+4;
  307.                 }
  308.             /* Check for PC relative with index */
  309.             else if (p[3] == ',' && (p[4] == 'A' || p[4] == 'D')
  310.                  && isRegNum(p[5])) {
  311.                 d->mode = PCIndex;
  312.                 d->index = p[5] - '0';
  313.                 if (p[4] == 'A')
  314.                     d->index += 8;
  315.                 if (p[6] == '.')
  316.                     /* Determine size of index register */
  317.                     if (p[7] == 'W') {
  318.                         d->size = WORD;
  319.                         return p+9;
  320.                         }
  321.                     else if (p[7] == 'L') {
  322.                         d->size = LONG;
  323.                         return p+9;
  324.                         }
  325.                     else {
  326.                         NEWERROR(*errorPtr, SYNTAX);
  327.                         return NULL;
  328.                         }
  329.                 else if (p[6] == ')') {
  330.                     /* Default size of index register is Word */
  331.                     d->size = WORD;
  332.                     return p+7;
  333.                     }
  334.                 else {
  335.                     NEWERROR(*errorPtr, SYNTAX);
  336.                     return NULL;
  337.                     }
  338.                 }
  339.             }
  340.         }
  341.  
  342.     /* If the operand doesn't match any pattern, return an error status */
  343.     NEWERROR(*errorPtr, SYNTAX);
  344.     return NULL;
  345. }
  346.  
  347.  
  348.