home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d186 / a68k.lha / A68k / Operands.c < prev    next >
C/C++ Source or Header  |  1989-02-26  |  17KB  |  558 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*              MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*          Copyright    (c) 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*        Operand    processor - January 10,    1989            */
  8. /*                                    */
  9. /*   This program may be copied    for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on    all copies of the source code.    Copying    for any    other use   */
  12. /*   without the consent of the    author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*        Originally published (in Modula-2) in            */
  17. /*        Dr.    Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*     AmigaDOS conversion copyright 1989 by Charlie Gibbs.        */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. #include <stdio.h>
  24. #include "a68kdef.h"
  25. #include "a68kglb.h"
  26.  
  27. /* Functions */
  28. extern int  LineParts(), Instructions(), ObjDir();
  29. extern int  ReadSymTab(), OpenIncl(), CountNest();
  30. extern long AddrBndW(),    AddrBndL(), GetValue(),    CalcValue();
  31. extern char *AddName(),    *GetField();
  32. extern struct SymTab *NextSym();
  33. extern struct SymTab **HashIt();
  34.  
  35. int GetArgs(), GetAReg(), GetInstModeSize(), GetMultReg();
  36.  
  37.  
  38.  
  39. int GetArgs (name) char    *name;
  40. /* Gets    macro arguments    and adds them to FNStack after adding "name".
  41.     Returns the    number of arguments added to the stack.
  42.     Note that this might not be    the full number    of arguments
  43.     provided if    the stack overflowed.                */
  44. {
  45.     register char *s, *t;
  46.     int    narg, instring;
  47.     char currarg[MAXLINE];        /* Current argument */
  48.  
  49.     narg = strlen (name) + 1;
  50.     Heap2Space (narg);            /* Find    space for name */
  51.     strcpy (NextFNS, name);        /* Add name to stack */
  52.     NextFNS += narg;            /* Bump    pointer    */
  53.     if (NextFNS    > High2)
  54.     High2 =    NextFNS;        /* Update high-water mark */
  55.  
  56.     narg = 0;                /* Argument counter */
  57.  
  58.     s =    Line + SrcLoc;            /* Now scan Line */
  59.     while (!isspace(*s)    && (*s != ';') && (*s != '\0')) {
  60.     t = currarg;
  61.     if (instring = (*s == '<'))     /* String delimiter */
  62.         s++;
  63.     while (1) {
  64.         if (*s == '\0')
  65.         break;            /* End of line */
  66.         if (instring) {
  67.         if (*s == '>') {
  68.             s++;
  69.             break;        /* End of string */
  70.         }
  71.         } else {
  72.         if ((*s    == ',')         /* End of operand */
  73.         || isspace(*s)        /* End of all operands */
  74.         || (*s == ';'))         /* Start of comments */
  75.             break;
  76.         }
  77.         *t++ = *s++;        /* Get a character */
  78.     }
  79.     *t++ = '\0';
  80.     Heap2Space (t -    currarg);    /* Check for space */
  81.     strcpy (NextFNS, currarg);    /* Store argument */
  82.     NextFNS    += t - currarg;        /* Next    available space    */
  83.     if (NextFNS > High2)
  84.         High2 = NextFNS;        /* High-water mark */
  85.     narg++;                /* Count arguments */
  86.     if (*s == ',')
  87.         s++;            /* Skip    over separator */
  88.     }
  89.     return (narg);            /* Successful completion */
  90. }
  91.  
  92.  
  93.  
  94. EffAdr (EA, Bad) register struct OpConfig *EA; int Bad;
  95. /* Adds    effective address field    to Op (BITSET representing opcode) */
  96. {
  97.     if ((1 << (EA->Mode    - 1)) IN Bad) {
  98.     Error (EA->Loc,    ModeErr);    /* Invalid mode    */
  99.     return;
  100.     } else if (EA->Mode    > 12)        /* Special modes */
  101.     return;
  102.     else if (EA->Mode <    8)        /* Register direct or indirect */
  103.     Op |= ((EA->Mode - 1) << 3) | EA->Rn;
  104.     else
  105.     Op |= 0x0038 | (EA->Mode - 8);    /* Absolute modes */
  106.     OperExt (EA);
  107. }
  108.  
  109.  
  110.  
  111. OperExt    (EA) register struct OpConfig *EA;
  112. /* Calculate operand Extension word, and check range of    operands */
  113. {
  114.     switch (EA->Mode) {
  115.     case AbsL:
  116.         break;   /*    No range checking needed */
  117.     case AbsW:
  118.     case ARDisp:
  119.     case PCDisp:
  120.         if ((EA->Value < -32768) ||    (EA->Value > 32767))
  121.         Error (EA->Loc,    SizeErr);
  122.         break;
  123.     case ARDisX:
  124.     case PCDisX:
  125.         if ((EA->Value < -128) || (EA->Value > 127))
  126.         Error (EA->Loc,    SizeErr);
  127.         EA->Value &= 0x00FF;              /* Displacement */
  128.         EA->Value |= EA->Xn    << 12;            /* Index reg. */
  129.         if (EA->X == Areg)       EA->Value |=    0x8000;    /* Addr. Reg. */
  130.         if (EA->Xsize == Long) EA->Value |=    0x0800;    /* Long    reg.  */
  131.         break;
  132.     case Imm:
  133.         if (Size ==    Word) {
  134.         if ((EA->Value < -32768) || (EA->Value > 65535L))
  135.             Error (EA->Loc, SizeErr);
  136.         } else if (Size == Byte)
  137.         if ((EA->Value < -128) || (EA->Value > 255))
  138.             Error (EA->Loc, SizeErr);
  139.         break;
  140.     }
  141. }
  142.  
  143.  
  144.  
  145. GetOperand (oper, op, pcconv)
  146. char *oper; register struct OpConfig *op; int pcconv;
  147. /* Finds mode and value    for source or destination operand.
  148.     If PC-relative addressing is permitted, "pcconv" gives the
  149.     offset to the displacement word; otherwise "pcconv" is zero. */
  150. {
  151.     register char *s, *t;
  152.     register int  i;
  153.     char *opend;
  154.     char UCoper[MAXLINE], tempop[MAXLINE];
  155.     int     rloc;
  156.     long templong;
  157.  
  158.     op->Value =    op->Defn = 0;
  159.     op->Mode = Null;
  160.     op->X    = X0;
  161.     op->Hunk = ABSHUNK;
  162.  
  163.     if (*oper == '\0')
  164.     return;                /* Nothing to process */
  165.  
  166.     s =    oper;
  167.     t =    UCoper;
  168.     while (*t++    = toupper (*s++))    /* Upper-case version */
  169.     ;
  170.     opend = s -    2;            /* Last    character of operand */
  171.  
  172.     if (*oper == '#') {                 /* Immediate */
  173.     op->Value = GetValue (oper+1, (op->Loc)+1);
  174.     op->Mode  = Imm;
  175.     op->Hunk  = Hunk2;
  176.     op->Defn  = DefLine2;
  177.     return;
  178.     }
  179.  
  180.     i =    IsRegister (oper, opend-oper+1);
  181.     if (i >= 0)    {
  182.     op->Mode = (i &    8) ? ARDir : DReg;    /* Register type */
  183.     op->Rn = i & 7;                /* Register number */
  184.     return;
  185.     } else if (i == -2)    {
  186.     op->Mode = MultiM;            /* Equated register list */
  187.     op->Value = Sym->Val;
  188.     return;
  189.     } else if ((*oper == '(') && (*opend == ')')) {
  190.     i = IsRegister (oper+1,    opend-oper-1);
  191.     if (i >= 8 && i    <= 15) {
  192.         op->Mode = ARInd;        /* Address Register indirect */
  193.         op->Rn = i - 8;
  194.         return;
  195.     } else if (i !=    -1) {
  196.         Error (op->Loc, AddrErr);    /* Data    register is invalid */
  197.         return;
  198.     }    /* else    may be parenthesized expression    */
  199.     } else if ((*oper == '(')           /* Post-increment */
  200.     && (*opend == '+')
  201.     && (*(opend-1) == ')')) {
  202.     op->Mode = ARPost;
  203.     op->Rn = GetAReg (oper+1, opend-oper-2,    op->Loc    + 1);
  204.     return;
  205.     } else if ((*oper == '-')           /* Pre-decrement */
  206.     && (*opend == ')')
  207.     && (*(oper+1) == '(')) {
  208.     i = IsRegister (oper+2,    opend-oper-2);
  209.     if (i >= 8 && i    <= 15) {
  210.         op->Mode = ARPre;
  211.         op->Rn = i - 8;
  212.         return;
  213.     } else if (i > 0) {
  214.         Error (op->Loc, AddrErr);    /* Data    register is invalid */
  215.         return;
  216.     }    /* else    parenthesized expression with leading minus? */
  217.     } else if (strcmp (UCoper, "SR") == 0) {
  218.     op->Mode = SR;                /* Status Register */
  219.     return;
  220.     } else if (strcmp (UCoper, "CCR") == 0) {
  221.     op->Mode = CCR;            /* Condition Code Register */
  222.     return;
  223.     } else if (strcmp (UCoper, "USP") == 0) {
  224.     op->Mode = USP;            /* User    Stack Pointer */
  225.     return;
  226.     }
  227.  
  228.     /* Try to split off    displacement (if present).
  229.     We'll assume we have a register expression if the operand
  230.     ends with a parenthesized expression not preceded by an
  231.     operator.  I know this code is a real kludge, but that's
  232.     the result of the bloody syntax.  Thanks, Motorola.    */
  233.  
  234.     s =    opend;                /* Last    character */
  235.     if (i = (*s    == ')'))                /* Trailing parenthesis? */
  236.     while (*(--s) != '(')           /* Find left parenthesis */
  237.         if (s <= oper)
  238.         break;
  239.     if (s <= oper)            /* Must    not be at beginning */
  240.     i = FALSE;
  241.     if (i) {
  242.     if (s == (oper+1)) {
  243.         if (*oper == '-')
  244.         i = FALSE;        /* Leading minus sign */
  245.     } else {
  246.         t =    s - 1;
  247.         if (*t == '*') {            /* Location counter? */
  248.         t--;
  249.         if (!IsOperator    (t) || (*t == ')'))
  250.             i =    FALSE;        /* No, it's multiplication */
  251.         } else if (IsOperator (t) && (*t !=    ')')) {
  252.         i = FALSE;        /* Preceded by an operator */
  253.         }
  254.     }
  255.     }
  256.  
  257.     if (i) {        /* Looks like a    displacement mode */
  258.     *s = '\0';
  259.     op->Value = GetValue (oper, op->Loc);    /* Displacement    */
  260.     op->Hunk  = Hunk2;            /* Hunk    number */
  261.     op->Defn  = DefLine2;            /* Line    where defined */
  262.     *s++ = '(';                             /* Restore parenthesis */
  263.  
  264.     rloc = op->Loc + s - oper;    /* The register    starts here */
  265.     s = GetField (s, tempop);    /* Get address register    */
  266.     if (*s == '\0')                 /* If there's no index register */
  267.         tempop[strlen(tempop)-1] = '\0';    /* chop parenthesis */
  268.  
  269.     if ((tempop[2] == '\0')
  270.     && (toupper (tempop[0])    == 'P')
  271.     && (toupper (tempop[1])    == 'C')) {
  272.         op->Mode = PCDisp;            /* Program Counter */
  273.         if (op->Hunk == CurrHunk) {
  274.         op->Value -= (AddrCnt+pcconv);    /* Adjust displacement */
  275.         op->Hunk = ABSHUNK;
  276.         }
  277.     } else {
  278.         if ((op->Value == 0)    /* If displacement is zero   */
  279.         && (op->Hunk == ABSHUNK)    /*  and    is absolute         */
  280.         && (op->Defn < LineCount)    /*  and    is already defined   */
  281.         && !(OpM68R    IN AdrModeA))    /*  and    isn't for a MOVEP    */
  282.         op->Mode = ARInd;    /*  forget the displacement. */
  283.         else
  284.         op->Mode = ARDisp;    /* Address reg.    w/displacement */
  285.         op->Rn = GetAReg (tempop, strlen (tempop), rloc);
  286.     }
  287.     if (*s != '\0') {               /* Index register is present */
  288.         if (op->Mode == PCDisp)
  289.         op->Mode = PCDisX;    /* Program Counter indexed */
  290.         else
  291.         op->Mode = ARDisX;    /* Address Register indexed */
  292.         if (*s != ',')
  293.         Error (op->Loc,    AddrErr);    /* Bad separator */
  294.         s++;                /* Skip    separator */
  295.         rloc = op->Loc + s - oper;        /* Start of index */
  296.         s =    GetField (s, tempop);        /* Get index register */
  297.         t =    tempop + strlen(tempop);
  298.         if (*s == '\0')
  299.         *(--t) = '\0';                  /* Chop parenthesis */
  300.         else
  301.         Error (rloc, AddrErr);        /* It better be    there */
  302.  
  303.         t -= 2;
  304.         if ((t < tempop) ||    (*t != '.')) {
  305.         op->Xsize = Word;    /* Size    defaults to 16 bits */
  306.         t += 3;
  307.         } else {
  308.         *t++ = '\0';                    /* Chop off size code */
  309.         switch (toupper    (*t)) {
  310.         case 'W':                       /* Word */
  311.             op->Xsize =    Word;
  312.             break;
  313.         case 'L':                       /* Long */
  314.             op->Xsize =    Long;
  315.             break;
  316.         default:
  317.             Error (op->Loc+s-1-oper, SizeErr);    /* Invalid size    */
  318.             op->Xsize =    Word;        /* Make    it word    for now    */
  319.         }
  320.         }
  321.         i =    IsRegister (tempop,t-tempop-1);    /* Get register    */
  322.         op->Xn = i & 7;            /* Index register number */
  323.         if ((i >= 0) && (i <= 7))
  324.         op->X =    Dreg;            /* Data    Register */
  325.         else if ((i    >= 8) && (i <= 15))
  326.         op->X =    Areg;            /* Address Register */
  327.         else
  328.         Error (rloc, AddrErr);        /* Invalid register */
  329.     }
  330.  
  331.     if ((op->Hunk >= 0) && (op->Hunk != ABSHUNK))
  332.         Error (op->Loc, RelErr);    /*  Relocatable    displacement */
  333.     return;
  334.     }
  335.  
  336.     if ((i = GetMultReg    (oper, op->Loc)) != 0) {
  337.     op->Value = (long) i;
  338.     op->Mode = MultiM;        /* Register list for MOVEM */
  339.     return;
  340.     }
  341.  
  342.     op->Value =    GetValue (oper,    op->Loc);    /* Get operand value */
  343.     op->Hunk  =    Hunk2;
  344.     op->Defn  =    DefLine2;
  345.     op->Mode  =    AbsL;        /* Assume absolute long    addressing */
  346.  
  347.     if (DefLine2 < LineCount) {        /* Backward reference */
  348.  
  349.     if (Hunk2 < 0) {
  350.         return;        /* External - leave as absolute    long */
  351.  
  352.     } else if (Hunk2 == CurrHunk) {    /* Reference to    current    hunk */
  353.         if (pcconv)    {
  354.         templong = op->Value-(AddrCnt+pcconv);    /* PC disp. */
  355.         if ((templong >= -32768) && (templong <= 32767)) {
  356.             op->Mode = PCDisp;    /* Convert to PC relative mode */
  357.             op->Value=templong;    /* Adjust displacement */
  358.             op->Hunk = ABSHUNK;
  359.         }
  360.         }
  361.  
  362.     } else if (Hunk2 == ABSHUNK) {    /* Absolute value */
  363.         if ((op->Value >= -32768) && (op->Value <= 32767))
  364.         op->Mode = AbsW;    /* Absolute word */
  365.  
  366.     } else if (SmallData &&    (op->Value>=0) && (op->Value<=65535L)) {
  367.         op->Mode = ARDisp;        /* Make    it a data reference */
  368.         op->Rn = 4;            /*  through register A4        */
  369.         op->Value -= 32768L;    /* Adjust displacement */
  370.         op->Hunk = ABSHUNK;
  371.     }
  372.     return;            /* Could default to absolute long */
  373.  
  374.     } else if (!SmallData) {    /* Fwd.    reference - if not small data */
  375.     return;            /*  leave as absolute long addressing */
  376.  
  377.     } else if (!Pass2) {    /* Forward reference, pass 1 */
  378.     op->Mode = ARDisp;    /* Assume displacement */
  379.     op->Rn = 4;        /*  from register A4   */
  380.     op->Hunk = ABSHUNK;
  381.     return;
  382.  
  383.     } else {            /* On pass 2 we    know what it is    */
  384.  
  385.     if (Hunk2 < 0) {
  386.         Error (op->Loc,FwdRef);    /* External - must be 32 bits */
  387.         op->Mode = AbsW;        /* Force absolute word anyway */
  388.  
  389.     } else if (Hunk2 == CurrHunk) {    /* It's in the current hunk */
  390.         op->Mode = PCDisp;        /* Convert to PC relative mode */
  391.         op->Value -= AddrCnt + pcconv;    /* Adjust displacement */
  392.         op->Hunk = ABSHUNK;
  393.         if (!pcconv    || (op->Value <    -32768)    || (op->Value >    32767))
  394.         Error (op->Loc,FwdRef);    /* It doesn't fit! */
  395.  
  396.     } else if (Hunk2 == ABSHUNK) {    /* It's absolute */
  397.         op->Mode = AbsW;        /* It has to fit in a word */
  398.         if ((op->Value < -32768) ||    (op->Value > 32767))
  399.         Error (op->Loc,FwdRef);    /* It doesn't fit! */
  400.  
  401.     } else {
  402.         op->Mode = ARDisp;        /* Assume data reference */
  403.         op->Rn = 4;            /*  through register A4     */
  404.         op->Value -= 32768L;    /* Adjust displacement */
  405.         if ((op->Value < -32768) ||    (op->Value > 32767))
  406.         Error (op->Loc,FwdRef);    /* It doesn't fit! */
  407.     }
  408.     }
  409. }
  410.  
  411.  
  412.  
  413. int GetMultReg (oper, loc) char    *oper; int loc;
  414. /* Builds a register mask for the MOVEM    instruction.
  415.     Returns the    mask in    the low-order portion of its value if
  416.     "oper" is a valid multiple-register list; otherwise returns 0. */
  417. {
  418.     register char *s, *t;
  419.     register int  j;
  420.     int    t1, t2;        /* Temporary variables for registers */
  421.     int    range;        /* We're processing a range of registers */
  422.     int    multext;    /* The result is built here */
  423.  
  424.     multext = 0;
  425.     range = FALSE;
  426.     s =    oper;
  427.     if (IsOperator (s))
  428.     return (0);            /* Starts with an operator! */
  429.  
  430.     while (1) {
  431.     for (t = s; *t;    t++) {
  432.         if ((*t == '-') || (*t == '/')) {
  433.         break;
  434.         }
  435.     }
  436.     if ((multext ==    0) && (*t == '\0'))
  437.         return (0);            /* Reject single term */
  438.     if ((t2    = IsRegister (s, t-s)) < 0)
  439.         return (0);            /* Not a recognizable register */
  440.  
  441.     if (!range) {
  442.         multext |= (1 << t2);    /* Single register */
  443.         t1 = t2;        /* Save    number in case it's a range */
  444.     } else {            /* Range of registers */
  445.         range = FALSE;
  446.         if (t1 > t2) {
  447.         j = t1;            /* Swap    registers if backwards */
  448.         t1 = t2;
  449.         t2 = j;
  450.         }
  451.         for    (j = t1; j <= t2; j++)
  452.         multext    |= (1 << j);    /* Mark    all registers in range */
  453.         if (*t == '-')
  454.         return (0);        /* Invalid range */
  455.     }
  456.     if (*t == '\0')
  457.         break;            /* Normal end of operand */
  458.     if (*t++ == '-')
  459.         range = TRUE;        /* Range indicator */
  460.     if (*t == '\0')
  461.         return (0);            /* Premature end of operand */
  462.     s = t;
  463.     }
  464.     return (multext);
  465. }
  466.  
  467.  
  468.  
  469. int GetAReg (op, len, loc) char    *op; int len, loc;
  470. /* Validate an address register    specification.
  471.     Valid specifications are A0    through    A7 , SP, or an EQUR label.
  472.     The    address    register number    will be    returned if it is valid.
  473.     Otherwise, Error will be called, using "loc" for the error
  474.     location (this is its only use), and zero (A0) will    be returned. */
  475. {
  476.     register int i;
  477.  
  478.     i =    IsRegister (op,    len);        /* Get register    number */
  479.     if ((i >= 8) && (i <= 15))
  480.     return (i - 8);            /* Valid address register */
  481.     else {
  482.     Error (loc, AddrErr);        /* Not an address register */
  483.     return (0);            /* Set to A0 */
  484.     }
  485. }
  486.  
  487.  
  488.  
  489. int IsRegister (op, len) char *op; int len;
  490. /* Check whether the current operand is    an address or data register.
  491.     Valid specifications are D0    throuth    D7, A0 through A7, SP,
  492.     or any symbol equated to a register    with the EQUR directive.
  493.     Return values:
  494.     0 through 7 - data registers 0 through 7 respectively
  495.     8 through 15 - address registers 0 through 7 respectively
  496.     -1 - not a recognizable    register
  497.     -2 - Equated register list for MOVEM instruction (REG)    */
  498. {
  499.     char tempop[MAXLINE];
  500.     register char *s;
  501.     register int  i;
  502.  
  503.     if (len == 2) {        /* Two-character specification */
  504.     i = toupper (*op);
  505.     s = op + 1;
  506.     if ((i == 'S') && (toupper (*s) == 'P')) {
  507.         return (15);        /* Stack Pointer */
  508.     } else if ((*s >= '0') && (*s <= '7')) {
  509.         if (i == 'A') {
  510.         return (*s - '0' + 8);  /* Address Register */
  511.         } else if (i == 'D') {
  512.         return (*s - '0');      /* Data Register */
  513.         }
  514.     }
  515.     }
  516.     if (!GotEqur)            /* If we have no EQURs to check    */
  517.     return (-1);            /*  don't waste any time here.  */
  518.     for    (i = 0,    s = op;    i < len; i++) {
  519.     if (IsOperator (s))
  520.         return (-1);        /* It sure isn't a label */
  521.     tempop[i] = *s++;
  522.     }
  523.     tempop[i] =    '\0';
  524.     if (ReadSymTab (tempop)) {
  525.     if (Sym->Flags & 0x60) {
  526.         AddRef (LineCount);        /* Found a register or list */
  527.         return ((Sym->Flags    & 0x20)    ? (int)    Sym->Val : -2);
  528.     }
  529.     }
  530.     return (-1);            /* Not a recognizable register */
  531. }
  532.  
  533.  
  534.  
  535. int GetInstModeSize (Mode) register int    Mode;
  536. /* Determines the size for the various instruction modes. */
  537. {
  538.     switch (Mode) {
  539.     case ARDisp:
  540.     case ARDisX:
  541.     case PCDisp:
  542.     case PCDisX:
  543.     case AbsW:
  544.         return (2);
  545.     case AbsL:
  546.         return (4);
  547.     case MultiM:
  548.         return (0);        /* Accounted for by code generator */
  549.     case Imm:
  550.         if (Size ==    Long)
  551.         return (4);
  552.         else
  553.         return (2);
  554.     default:
  555.         return (0);
  556.     }
  557. }
  558.